# SeriousLetter API Schema (cached from /api/v1/discover) **Base URL:** https://jobs.seriousletter.com **Auth:** X-API-Token header **Rate limits:** 100/min, 1000/day per token **Prod token (Matthias):** 9955f8699964b70eee3b4acf8b7ca5cf7f6997ddb23d483f1c5f178754f11196 **Prod token (Gina):** a073d1c4f09049c4d7750a99344a6f9995b0271afff68acb6c85fb636f0b914b **Dev token:** d6b3f193ce94f4d42b92dab708c06cb050cf861fdf35050a7f471a8ada1edf2b ## jobs Job applications tracked by the user - **GET /api/v1/jobs** - List all jobs (newest first) - status: optional filter (applied/rejected/not_applying/outdated) - page: default 1 - page_size: default 20, max 100 - **GET /api/v1/jobs/search** - Fuzzy search jobs by company or position title - q: required search query - page: default 1 - page_size: default 20 - **GET /api/v1/jobs/{job_uuid}** - Get full job detail by UUID - job_uuid: path parameter - **GET /api/v1/jobs/{job_uuid}/arbeit** - Get job formatted for arbeit.swiss form fields - job_uuid: path parameter - **GET /api/v1/jobs/{job_uuid}/status-history** - Get status change history for a job - job_uuid: path parameter - **POST /api/v1/jobs** - Create a new job application [MUTATES] - company: required — company name - position_title: required — job title - company_uuid: optional — UUID of existing company record; copies address/contact from that company - status: optional — defaults to 'opportunity'; valid: opportunity/applied/rejected/not_applying/outdated - source_url: optional — URL where the job listing was found - application_url: optional — URL of the application form or portal - location: optional — job location (city, country, or 'Remote') - salary_range: optional — salary range as free text (e.g. 'CHF 120000-150000') - priority: optional — integer 1-5 (1=highest priority) - language: optional — job language code (e.g. 'en', 'de', 'fr') - job_description: optional — full job description in markdown - company_address_line1: optional — street address line 1 - company_address_line2: optional — street address line 2 - company_city: optional — city - company_postal_code: optional — postal/ZIP code - company_country_code: optional — ISO 2-letter country code (e.g. 'CH', 'DE', 'FR') - company_country: optional — country name (e.g. 'Switzerland', 'Germany') - is_recruiting_agency: optional — boolean; true if company is a recruiter/agency - contact_person: optional — name of the contact person at the company - applied_date: optional — YYYY-MM-DD - interview_date: optional — YYYY-MM-DD - rejected_date: optional — YYYY-MM-DD - not_applying_date: optional — YYYY-MM-DD - outdated_date: optional — YYYY-MM-DD - **PUT /api/v1/jobs/{job_uuid}** - Update a job (partial updates supported). When status changes, corresponding date is auto-set. [MUTATES] - All POST fields accepted (all optional), plus: - status_change_notes: optional — note to record alongside the status change in history - **DELETE /api/v1/jobs/{job_uuid}** - Delete a job and all its job-specific CVs [MUTATES] - WARNING: Irreversible. Deletes the job and all attached job CVs. - **GET /api/v1/jobs/{job_uuid}/notes** - List all notes for a job (newest first). Returns {notes: [...], total: N} - **POST /api/v1/jobs/{job_uuid}/notes** - Create a note on a job. Accepts {text, category?, note_date?} or legacy {note, date?} [MUTATES] - text: required note text (or note for backward compat) - category: optional: application/interview/rejection/status/general - note_date: optional YYYY-MM-DD (defaults to today) - **PATCH /api/v1/jobs/{job_uuid}/notes/{note_id}** - Update a note. Partial updates: {text?, category?, note_date?} [MUTATES] - **DELETE /api/v1/jobs/{job_uuid}/notes/{note_id}** - Delete a note [MUTATES] - WARNING: Irreversible ## companies Company records (reusable address/contact info across jobs) - **GET /api/v1/companies** - List companies (search by name/city/contact with ?q=) - q: optional search query - page: default 1 - page_size: default 20 - **GET /api/v1/companies/{company_uuid}** - Get a single company by UUID - **POST /api/v1/companies** - Create a new company [MUTATES] - name: required — company name - website: optional — company website URL - address_line1: optional — street address line 1 - address_line2: optional — street address line 2 - city: optional — city - postal_code: optional — postal/ZIP code - country_code: optional — ISO 2-letter country code (e.g. 'CH', 'FR', 'DE') - country: optional — country name (e.g. 'Switzerland', 'France') - contact_person: optional — name of primary contact - contact_email: optional — contact email address - contact_phone: optional — contact phone number - notes: optional — free-text notes about the company - is_recruiting_agency: optional — boolean; true if this is a recruiter/staffing agency - **PUT /api/v1/companies/{company_uuid}** - Update a company (partial updates, all fields optional) [MUTATES] - **DELETE /api/v1/companies/{company_uuid}** - Delete a company [MUTATES] - WARNING: Irreversible. ## letters Cover letters attached to jobs - **GET /api/v1/jobs/{job_uuid}/letters** - List all letters for a job - **GET /api/v1/letters/{letter_id}** - Get a single letter by ID (integer, not UUID) - **POST /api/v1/jobs/{job_uuid}/letters** - Create a letter for a job (manual content, no AI generation) [MUTATES] - version_name: required - content: required markdown - tone: optional - language: optional - **PUT /api/v1/letters/{letter_id}** - Update a letter's content or name [MUTATES] - final_content: optional - version_name: optional - **DELETE /api/v1/letters/{letter_id}** - Delete a letter [MUTATES] - WARNING: Irreversible. ## cvs CV profiles — general (user-level) and job-specific. Each CV can optionally link an executive summary (prepended) and portfolio document (appended) for combined PDF exports. - **GET /api/v1/profiles** - List general CV profiles (not job-specific). Returns executive_summary_uuid and portfolio_document_uuid if set. - **GET /api/v1/jobs/{job_uuid}/cvs** - List job-specific CVs attached to a job. Returns executive_summary_uuid and portfolio_document_uuid if set. - **POST /api/v1/jobs/{job_uuid}/cvs/copy/{profile_uuid}** - Deep-copy a general CV to a job as a job-specific CV [MUTATES] - name: optional — override the auto-generated name for the copied CV - portfolio_document_uuid: optional — UUID of a portfolio document to attach - executive_summary_uuid: optional — UUID of an executive summary to attach - **PATCH /api/v1/jobs/{job_uuid}/cvs/{profile_uuid}/executive-summary** - Set or clear the executive summary on a job CV. Pass null to clear. [MUTATES] - executive_summary_uuid: UUID or null - **PATCH /api/v1/jobs/{job_uuid}/cvs/{profile_uuid}/portfolio** - Set or clear the portfolio document on a job CV. Pass null to clear. [MUTATES] - portfolio_document_uuid: UUID or null - **PATCH /api/v1/jobs/{job_uuid}/cvs/{profile_uuid}/letter-template** - Set or clear the preferred letter template on a job CV. Pass null to clear. [MUTATES] - preferred_letter_template: template ID or null - **DELETE /api/v1/jobs/{job_uuid}/cvs/{profile_uuid}** - Delete a job-specific CV [MUTATES] - WARNING: Irreversible. ## export PDF export endpoints — all read-only, return application/pdf - **GET /api/v1/export/letters/{letter_id}/pdf** - Export a cover letter as PDF - template: optional (modern/german/professional/european) — fallback: starred CV preference > user default > system default - **GET /api/v1/export/letters/{letter_id}/combined-pdf** - Export combined PDF: exec summary + letter + CV + portfolio - letter_template: optional — fallback: CV preference > user default > system default - cv_template: optional — fallback: CV preference > system default - cv_uuid: optional — override which CV to use - **GET /api/v1/export/cvs/{profile_uuid}/pdf** - Export a CV profile as PDF - template: optional (modern/professional/creative/sidebar) — fallback: CV preference > system default - **GET /api/v1/export/executive-summaries/{summary_uuid}/pdf** - Download an executive summary PDF ## executive_summaries Executive summary PDFs (e.g. Elevator Pitch decks) that can be prepended before CVs in combined exports - **GET /api/v1/executive-summaries** - List available executive summaries - language: optional filter (de/en/fr) - **GET /api/v1/export/executive-summaries/{summary_uuid}/pdf** - Download an executive summary PDF file ## portfolio_documents Portfolio documents (project portfolios) that can be appended after CVs in combined exports - **GET /api/v1/portfolio-documents** - List available portfolio documents - language: optional filter ## Key field names (to avoid discover calls) **Job fields:** company, position_title, company_uuid, status, applied_date, created_at, interview_date, rejected_date, not_applying_date, outdated_date, source_url, application_url, location, salary_range, priority, language, job_description, company_address_line1, company_address_line2, company_city, company_postal_code, company_country_code, company_country, is_recruiting_agency, contact_person **Company fields:** name, website, address_line1, address_line2, city, postal_code, country_code, country, contact_person, contact_email, contact_phone, notes, is_recruiting_agency **Letter fields:** POST: content, version_name, tone, language. PUT: final_content, version_name **Note fields:** text (or legacy: note), category (application/interview/rejection/status/general), note_date (YYYY-MM-DD) **Valid statuses:** opportunity (default on POST), editing, applied, rejected, not_applying, outdated **POST /jobs ignores invalid status** - always follow up with PUT to set status to editing/not_applying etc.