{"openapi":"3.1.0","info":{"title":"Curriculo Résumé API","summary":"Read a résumé into structured JSON, and generate, edit, translate or answer questions about one — through two authenticated endpoints.","description":"Turn a résumé into **structured, improvable, and translatable** data. No sign-up,\nno dashboard, and no résumé IDs to track: authenticate with your client token and\nwork in **any language**.\n\n---\n\n### 🔑 Authentication\n\nEvery request carries your client token:\n\n```http\nAuthorization: Bearer <your-token>\n```\n\nClick the green **Authorize** button (top-right), paste your token, and you can\nrun live requests straight from this page. Requests without a valid token are\nrejected with **`401`**.\n\n> **Need a token?** Tokens are issued by the Curriculo team. See the **Client\n> Integration Guide** you were given, or get in touch.\n\n### 🧭 Which endpoint?\n\n| | **`POST /parse/`** | **`POST /prompt/`** |\n|---|---|---|\n| **Use it to** | read a CV into structured JSON | generate, edit, ask about, or translate a résumé |\n| **You send** | a file, every time | plain-language instructions |\n| **State** | none — each call is independent | your token's résumé, remembered between calls |\n| **Best for** | bulk intake, ATS import, screening | résumé building and improvement |\n\nMost integrations only need one of the two.\n\n### 📄 Reading a CV — `POST /parse/`\n\nSend a PDF or DOCX (up to 10 MB) and get its contents back as JSON: name,\ncontact details, education, experience, skills, certifications, projects and\nmore. **Stateless** — nothing is stored, so every call is independent and you\ncan send a different candidate each time.\n\nValues come back in the résumé's **own language and script** — the parser never\ntranslates. A field the résumé doesn't contain comes back empty (`\"\"`, `[]`,\n`{}`) rather than absent; the list fields are always arrays, so you can iterate\nthem unconditionally. See **`ParsedResume`** in the **Schemas** section below.\n\n### ✍️ Improving a résumé — `POST /prompt/`\n\nYour token is pinned to **one résumé**:\n\n1. **First call** — attach your résumé PDF (`file`) to seed it.\n2. **Every call after** — just send `prompt_text` to improve, restructure, ask\n   about, or translate that same résumé. No file needed.\n\nWrite `prompt_text` in **any language** — *\"add Python to my skills\"* or\n*\"技術スキルに Python を追加\"* do the same thing. To render the résumé in a specific\nlanguage, set the **`language`** field (e.g. `ko`, `ja`, `fr`). You never write\n*\"translate to…\"* in the text.\n\nYou get back one JSON response: an `assistant_message` to show your user, plus\nthe updated résumé as structured segments under `ai_response`.\n\n### 📏 Limits, timeouts and concurrency\n\n| | Value | What you see when exceeded |\n|---|---|---|\n| Document upload (`/parse/`, `/evaluate/`, `/prompt/`, `/translate/` files) | **10 MB** per file | `413` |\n| Text (`/detect-language/`, `/translate/` items) | **50,000 characters** per item | `413` |\n| Batch size | **10 documents** or **200 texts** per request | `413` |\n| Request timeout | **300 s** per request (a batch shares it) | `504` — retry once; narrower inputs return faster |\n| Concurrency | **3 heavy operations at a time per deployment**, queued beyond that | slower responses, then `504` if the queue outlasts the timeout |\n| Transcript document on `/summary/` (PDF/DOCX instead of a recording) | **50 MB** | `413` |\n| Duplicate JSON keys (`/translate/`, `/summary/`, `/detect-language/`) | rejected | `400` naming the key — the last value is never silently kept |\n| Password-protected PDF | rejected | `400` — remove the password and resend |\n\nEvery response carries **`X-Curriculo-Request-Id`**. Quote it when you contact\nsupport and we can find the exact call.\n\n### ⏳ Long work — the async lane\n\n`/parse/`, `/evaluate/`, `/summary/`, `/transcribe/` and `/translate/` also exist as **`POST /{op}/async`** on\n`api.curriculo.me/public/` for work that should not hold a connection open —\na backlog of CVs, or an hour-long interview recording. Most take **links, not\nuploads** (translate takes `text`/`texts`), and answer **`202 {\"task_id\": ..., \"status\": \"queued\"}`** at once:\n\n| Endpoint | Body |\n|---|---|\n| `POST /parse/async` | `{\"file_urls\": [\"https://…/cv.pdf\", …]}` |\n| `POST /evaluate/async` | `{\"resume_urls\": [...], \"job_details\": \"…\"}` or `\"job_id\"` |\n| `POST /summary/async` | `{\"media_url\": \"https://…/interview.mp4\", \"language\": \"ko\"}` — recordings up to **2 hours**, audio or video |\n| `POST /transcribe/async` | `{\"media_url\": \"https://…/interview.mp4\"}` — same media as summary, transcript only |\n| `POST /translate/async` | `{\"text\": \"…\", \"source_language\": \"en\", \"target_language\": \"fr\"}` — or `texts` (not both) |\n\nAll five accept an optional **`callback_url`** (https, publicly reachable);\nyou then also receive a one-time `callback_secret` and each delivery is signed\n`X-Curriculo-Signature: sha256=<hmac of the raw body>`. Omit it and collect the\nresult yourself with **`GET /{op}/tasks/{task_id}`** — the result stays there\neither way. A task that fails is never billed.\n\n---\n\n<sub>© Curriculo · Résumé API — for the intended recipient only.</sub>\n","contact":{"name":"Curriculo Team","url":"https://curriculo.me/","email":"founder@curriculo.me"},"license":{"name":"© Curriculo — All rights reserved."},"version":"1.0.0"},"servers":[{"url":"/public"}],"paths":{"/prompt/":{"post":{"tags":["resume"],"summary":"Generate, edit, ask about or translate your résumé","description":"Run one instruction against your résumé and return the result.\n\nThis single endpoint covers the whole flow:\n\n* **Seed** — first call: attach a PDF (`file`) to import an existing CV.\n* **Edit / add** — *\"add a Project section\"*, *\"make my summary punchier\"*.\n* **Ask** — *\"how many years of experience do I have?\"* (answer only,\n  résumé unchanged).\n* **Translate** — set `language` to render the résumé in another language.\n\n**Authentication.** Send `Authorization: Bearer <token>`. Your token is\npinned to exactly one résumé, so you never pass a `resume_id` — it is\nderived from the token. An unknown/missing token returns **401**.\n\n**Response.** See `PublicPromptResponse`: always a `mode` and an\n`assistant_message`; edits additionally return the updated résumé under\n``ai_response``.","operationId":"prompt_prompt__post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"X-Curriculo-Target-Resume-Id","in":"header","required":false,"schema":{"anyOf":[{"type":"string","minLength":1,"maxLength":255},{"type":"null"}],"description":"Console keys through the gateway only. An account-owned resume_id from GET /prompt/resumes. Updates that saved context; never creates one. Mutually exclusive with X-Curriculo-User-Id.","title":"X-Curriculo-Target-Resume-Id"},"description":"Console keys through the gateway only. An account-owned resume_id from GET /prompt/resumes. Updates that saved context; never creates one. Mutually exclusive with X-Curriculo-User-Id."},{"name":"X-Curriculo-User-Id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Console keys only, via the gateway: case-sensitive end-user ID scoped to your account. Use 1-128 ASCII letters, digits, _, ., :, @ or -, starting with a letter or digit. New IDs create a customer/resume context; reuse for follow-ups. Omit for the original pinned resume. Responses include customer_id and resume_id when selected.","title":"X-Curriculo-User-Id"},"description":"Console keys only, via the gateway: case-sensitive end-user ID scoped to your account. Use 1-128 ASCII letters, digits, _, ., :, @ or -, starting with a letter or digit. New IDs create a customer/resume context; reuse for follow-ups. Omit for the original pinned resume. Responses include customer_id and resume_id when selected."}],"requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/Body_prompt_prompt__post"}}}},"responses":{"200":{"description":"Résumé processed. See the schema for the two response shapes.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicPromptResponse"}}}},"401":{"description":"Missing or invalid API token.","content":{"application/json":{"example":{"detail":"Invalid API token."},"schema":{"$ref":"#/components/schemas/PublicApiError"}}}},"413":{"description":"Uploaded PDF exceeds the 10 MB limit.","content":{"application/json":{"example":{"detail":"File too large (max 10 MB)."},"schema":{"$ref":"#/components/schemas/PublicApiError"}}}},"504":{"description":"Processing took longer than the server timeout.","content":{"application/json":{"example":{"detail":"Prompt processing timed out"},"schema":{"$ref":"#/components/schemas/PublicApiError"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/parse/":{"post":{"tags":["resume"],"summary":"Extract a résumé into structured JSON","description":"Read a CV and return its contents as structured JSON.\n\nA single, **stateless** call: send a document, get the extracted résumé\nback. Nothing is stored and nothing is remembered between calls — send\nthe same file twice and you get the same answer twice, and send a\ndifferent candidate's CV on the next call and it is treated as a fresh,\nunrelated document.\n\n**Any format, any industry, any language.** PDF and DOCX are both\naccepted. Values come back in the résumé's **own language and script** —\nthe parser never translates or transliterates.\n\n**Authentication.** Send `Authorization: Bearer <token>`. An unknown or\nmissing token returns **401**.\n\n**Response.** See `ParsedResume`. A field the résumé doesn't contain\ncomes back empty (`\"\"`, `[]`, `{}`) rather than absent; the list fields\nare always arrays, so you can iterate them unconditionally.\n\n*Looking to edit, improve or translate a résumé rather than just read\none? Use `POST /prompt/`.*","operationId":"parse_parse__post","requestBody":{"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/Body_parse_parse__post"}}}},"responses":{"200":{"description":"The résumé, extracted into structured JSON.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ParsedResume"}}}},"400":{"description":"The uploaded file is empty.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicApiError"},"example":{"detail":"Uploaded file is empty."}}}},"401":{"description":"Missing or invalid API token.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicApiError"},"example":{"detail":"Invalid API token."}}}},"413":{"description":"Uploaded file exceeds the 10 MB limit.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicApiError"},"example":{"detail":"File too large. Maximum size is 10 MB."}}}},"504":{"description":"Parsing took longer than the server timeout.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicApiError"},"example":{"detail":"Resume parsing timed out"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/translate/":{"post":{"tags":["language"],"summary":"Translate one string, several strings, or a document","description":"Translate text or documents — JSON body or multipart file upload.\n\nSend `text` for one string and the response carries `translation`; send\n`texts` for several and it carries `translations` in the same order.\nUpload `files` (PDF or DOCX) to translate whole documents.","operationId":"translate_translate__post","requestBody":{"content":{"application/json":{"schema":{"properties":{"text":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Text","description":"A single string to translate. Use this for one sentence or paragraph; the response carries `translation` rather than a list.","examples":["Led the billing rewrite."]},"texts":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Texts","description":"Several strings to translate, in order (max 200 strings, 50,000 characters total). The response list keeps this order.","examples":[["Led the billing rewrite.","Mentored three juniors."]]},"target_language":{"type":"string","title":"Target Language","description":"Any target language, as an ISO 639-1 code.","examples":["ko"]},"source_language":{"type":"string","title":"Source Language","description":"ISO 639-1 code of the input text (default `en`).","default":"en","examples":["en"]}},"type":"object","required":["target_language"],"title":"PublicTranslateRequest","description":"Request body for ``POST /translate/``.\n\n``texts`` is how the ATS calls the internal translator — it renders a whole\npage of UI strings at once — and requiring it here made a client wrap a\nsingle sentence in an array to say the simplest thing this endpoint does.\n``text`` is the singular spelling every other public operation already has\n(``file``/``files``, ``resume_pdf``/``resume_pdfs``, ``text``/``texts`` on\n``/detect-language/``), and one string in returns one string out."}},"multipart/form-data":{"schema":{"properties":{"files":{"items":{"type":"string","format":"binary"},"type":"array","description":"Documents to translate — PDF or DOCX. Send one file or several; the response keeps your order."},"target_language":{"type":"string","description":"ISO 639-1 code to translate into, e.g. `ko`.","examples":["ko"]},"source_language":{"type":"string","description":"ISO 639-1 code of the source. Defaults to `en`.","examples":["en"]},"reqj":{"type":"string","description":"Alternative to `files`: the JSON body above, as a string, for clients that can only send multipart."}},"type":"object","title":"Document translation"}}},"required":true},"responses":{"200":{"description":"A singular `translation` for `text`, or ordered `translations` for `texts`. `ok=false` means every engine failed and source text was returned.","content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/PublicSingleTranslateResponse"},{"$ref":"#/components/schemas/TranslateResponse"}],"title":"Response Translate Translate  Post"}}}},"400":{"description":"Neither `text` nor `texts` carried anything to translate.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicApiError"},"example":{"detail":"Send `text` (one string) or `texts` (several)."}}}},"401":{"description":"Missing or invalid API token.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicApiError"},"example":{"detail":"Invalid API token."}}}},"413":{"description":"Batch exceeds 200 strings or 50,000 total characters.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicApiError"},"example":{"detail":"Batch too large (max 200 strings / 50,000 characters)."}}}},"504":{"description":"Translation took longer than the server timeout.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicApiError"},"example":{"detail":"Translation timed out"}}}}},"security":[{"HTTPBearer":[]}]}},"/detect-language/":{"post":{"tags":["language"],"summary":"Detect the language of a text (stateless)","description":"Detect the language of one text, or of many in one call — stateless.\n\nSend a text; get back its language as an ISO 639-1 code (e.g. `ko`).\nDetection runs offline (langid) with an LLM\nfallback for low-confidence texts.\n\nNothing is stored and the token's pinned résumé is never read or\ntouched — the token is the auth gate only.\n\n**Authentication.** Send `Authorization: Bearer <token>`. An unknown or\nmissing token returns **401**.","operationId":"detect_language_detect_language__post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicDetectLanguageRequest"}}},"required":true},"responses":{"200":{"description":"The detected language, as an ISO 639-1 code.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DetectLanguageResponse"}}}},"400":{"description":"The `text` is blank.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicApiError"},"example":{"detail":"text must not be blank."}}}},"401":{"description":"Missing or invalid API token.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicApiError"},"example":{"detail":"Invalid API token."}}}},"413":{"description":"Text exceeds 50,000 characters.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicApiError"},"example":{"detail":"Text too long (max 50,000 characters)."}}}},"504":{"description":"Detection took longer than the server timeout.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicApiError"},"example":{"detail":"Language detection timed out"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/evaluate/":{"post":{"tags":["evaluation"],"summary":"Evaluate a candidate against a job (stateless)","description":"Evaluate candidates against your job — stateless, nothing stored.\n\nSend the CV and the job. The job is `job_details` — the description as\nyou already hold it, pasted straight from your careers page; a JSON\nobject works too if you keep structured requirements. Nothing has to be\nregistered or configured first. You get back suitability scores, fit\nanalysis and gap detection. `language` (ISO 639-1, e.g. `ko`) renders\nthe candidate-facing prose in that language.\n\nEvaluating a backlog against one job? `POST /jobs/` returns a `job_id`\nyou can send instead of repeating the description. That is an\noptimisation, not a step — `job_details` alone is the whole contract.\n\nOne CV returns the evaluation directly; several return a `results` list\nin input order, where a CV that fails carries its own error and leaves\nthe rest of the batch intact.\n\nNothing is stored: no evaluation is persisted and the token's pinned\nrésumé is never read or touched — the token is the auth gate only. A\nregistered job is the one exception, and it stores only the requirements\nyou sent, never a candidate.\n\n**Authentication.** Send `Authorization: Bearer <token>`. An unknown or\nmissing token returns **401**.","operationId":"evaluate_evaluate__post","requestBody":{"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/Body_evaluate_evaluate__post"}}}},"responses":{"200":{"description":"The evaluation result: suitability scores, fit analysis and gap detection for the candidate against the job.","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Evaluate Evaluate  Post"},"example":{"overall_score":72.5,"fit_analysis":"Strong backend experience; gaps in Kubernetes.","gaps":["Kubernetes"]}}}},"400":{"description":"The uploaded file is empty, or `job_details` is not valid JSON (the impl's own validation).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicApiError"},"example":{"detail":"Uploaded file is empty."}}}},"401":{"description":"Missing or invalid API token.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicApiError"},"example":{"detail":"Invalid API token."}}}},"413":{"description":"Uploaded file exceeds the 10 MB limit.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicApiError"},"example":{"detail":"File too large. Maximum size is 10 MB."}}}},"504":{"description":"Evaluation took longer than the server timeout.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicApiError"},"example":{"detail":"Applicant evaluation timed out"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/jobs/":{"post":{"tags":["evaluation"],"summary":"Optional: register a job once to avoid repeating it (not an ATS job)","description":"Register a job's requirements and get an id back — optional.\n\nYou never need this endpoint: `POST /evaluate/` takes the job\ndescription directly, every time. It exists for one case — evaluating a\nbacklog against a single job, where repeating the same description on\nevery request is wasteful. Register it once here, then send the returned\n`job_id` instead of `job_details`.\n\nThis is not an ATS job: no organisation, no board, no pipeline, no\nlisting endpoint. It stores the requirements text and nothing else.\n\nOnly your requirements are stored — no candidate, no CV, no result — and\nthe job is readable only by the token that created it.\n\n**Authentication.** Send `Authorization: Bearer <token>`. An unknown or\nmissing token returns **401**.","operationId":"register_job_jobs__post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicJobRequest"}}},"required":true},"responses":{"200":{"description":"Job registered; use the returned job_id on /evaluate/.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicJobResponse"}}}},"400":{"description":"Blank job_details."},"401":{"description":"Missing or unknown API token."},"503":{"description":"Job registration is temporarily unavailable."},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/summary/":{"post":{"tags":["interviews"],"summary":"Summarize an interview — send JSON text or upload a file (PDF/DOCX/video/audio)","description":"Summarize interviews - accepts JSON body or multipart file/recording upload.","operationId":"summary_summary__post","requestBody":{"content":{"application/json":{"schema":{"anyOf":[{"properties":{"interview_id":{"type":"string","title":"Interview Id","description":"Optional caller-chosen identifier for this interview, echoed back unchanged (log label only — nothing is looked up or persisted). The async lane treats it the same way.","default":"","examples":["iv-2026-000123"]},"transcript_text":{"type":"string","title":"Transcript Text","description":"Raw interview transcript. Plain text; structured turns may additionally be supplied via transcript_entries.","examples":["Interviewer: Tell me about your React experience...\nCandidate: I've shipped..."]},"transcript_entries":{"anyOf":[{"items":{"properties":{"participant":{"type":"string","title":"Participant","description":"Speaker label, e.g. 'interviewer' or the candidate's name."},"text":{"type":"string","title":"Text","description":"What this speaker said."},"startTime":{"type":"string","title":"Starttime","description":"Turn start offset (string, as produced by the Meet transcript pipeline).","default":""},"endTime":{"type":"string","title":"Endtime","description":"Turn end offset (string, as produced by the Meet transcript pipeline).","default":""}},"type":"object","required":["participant","text"],"title":"_PublicSummaryTranscriptEntry","description":"One structured turn in an interview transcript (public wire format).\n\nField names use camelCase (``startTime``/``endTime``) and are STRING\noffsets, matching the internal ``TranscriptEntry`` (ATS\n``MeetTranscriptEntry`` mirror) contract exactly — callers can forward\ntheir existing payloads unchanged and entries pass through unmodified."},"type":"array"},{"type":"null"}],"title":"Transcript Entries","description":"Optional structured turns; used for speaking-time analytics when supplied."},"language":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Language","description":"ISO 639-1 code to render the summary prose in. Omit or 'en' for English.","examples":["fr"]}},"type":"object","required":["transcript_text"],"title":"_PublicSummaryRequest","description":"Body for the public ``/summary/`` endpoint."},{"items":{"properties":{"interview_id":{"type":"string","title":"Interview Id","description":"Optional caller-chosen identifier for this interview, echoed back unchanged (log label only — nothing is looked up or persisted). The async lane treats it the same way.","default":"","examples":["iv-2026-000123"]},"transcript_text":{"type":"string","title":"Transcript Text","description":"Raw interview transcript. Plain text; structured turns may additionally be supplied via transcript_entries.","examples":["Interviewer: Tell me about your React experience...\nCandidate: I've shipped..."]},"transcript_entries":{"anyOf":[{"items":{"properties":{"participant":{"type":"string","title":"Participant","description":"Speaker label, e.g. 'interviewer' or the candidate's name."},"text":{"type":"string","title":"Text","description":"What this speaker said."},"startTime":{"type":"string","title":"Starttime","description":"Turn start offset (string, as produced by the Meet transcript pipeline).","default":""},"endTime":{"type":"string","title":"Endtime","description":"Turn end offset (string, as produced by the Meet transcript pipeline).","default":""}},"type":"object","required":["participant","text"],"title":"_PublicSummaryTranscriptEntry","description":"One structured turn in an interview transcript (public wire format).\n\nField names use camelCase (``startTime``/``endTime``) and are STRING\noffsets, matching the internal ``TranscriptEntry`` (ATS\n``MeetTranscriptEntry`` mirror) contract exactly — callers can forward\ntheir existing payloads unchanged and entries pass through unmodified."},"type":"array"},{"type":"null"}],"title":"Transcript Entries","description":"Optional structured turns; used for speaking-time analytics when supplied."},"language":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Language","description":"ISO 639-1 code to render the summary prose in. Omit or 'en' for English.","examples":["fr"]}},"type":"object","required":["transcript_text"],"title":"_PublicSummaryRequest","description":"Body for the public ``/summary/`` endpoint."},"type":"array","description":"Up to 10 interviews in one call; results come back in your order."}],"title":"One interview, or a list of them"}},"multipart/form-data":{"schema":{"properties":{"media":{"items":{"type":"string","format":"binary"},"type":"array","description":"Interview recordings or transcript documents — video, audio, PDF or DOCX. A recording is transcribed first; a 503 means transcription is not enabled on this deployment."},"interview_id":{"type":"string","description":"Your identifier for this interview. Defaults to the uploaded filename.","examples":["iv-2026-000123"]},"language":{"type":"string","description":"ISO 639-1 code for the summary prose.","examples":["en"]},"reqj":{"type":"string","description":"Alternative to `media`: the JSON body above, as a string, for clients that can only send multipart."}},"type":"object","title":"Recording or transcript upload"}}},"required":true},"responses":{"200":{"description":"Interview summary generated.","content":{"application/json":{"schema":{}}}},"400":{"description":"Blank transcript, invalid request body, or unreadable file."},"401":{"description":"Missing or unknown API token."},"413":{"description":"Transcript or file exceeds the size limit."},"503":{"description":"A recording was sent but transcription is not enabled here."},"504":{"description":"Transcription or summary generation timed out."}},"security":[{"HTTPBearer":[]}]}},"/transcribe/":{"post":{"tags":["transcription"],"summary":"Transcribe audio or video without generating a summary","operationId":"transcribe_transcribe__post","requestBody":{"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/Body_transcribe_transcribe__post"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicTranscribeResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/parse/async":{"post":{"tags":["Async lane"],"summary":"Parse a backlog of CVs from links, without holding a connection open","description":"Answers **202** at once with a `task_id`; the work runs on our side. One `result` item per link, in order, same shape as `POST /parse/`. Poll `GET /parse/tasks/{task_id}`, or give a `callback_url` and we POST the finished task there, signed. A task that fails is never billed. Served by the API gateway; same `Authorization: Bearer key_…` as every other call.","x-served-by":"gateway","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"file_urls":{"type":"array","minItems":1,"maxItems":10,"items":{"type":"string","format":"uri"},"description":"Public https links to the PDF or DOCX résumés. Fetched by us; not uploaded."},"callback_url":{"type":"string","format":"uri","maxLength":2048,"description":"Optional. https only, publicly reachable (private addresses are refused at delivery time), no credentials in the URL. Omit it and collect the result with GET /{op}/tasks/{task_id}."}},"required":["file_urls"]}}}},"responses":{"202":{"description":"Accepted.","content":{"application/json":{"schema":{"type":"object","properties":{"task_id":{"type":"string","format":"uuid"},"status":{"type":"string","enum":["queued"]},"callback_secret":{"type":"string","description":"Only when callback_url was given. `whsec_…`, shown exactly once: HMAC-SHA256 key for `X-Curriculo-Signature: sha256=<hex>` over the raw callback body."}},"required":["task_id","status"]}}}},"400":{"description":"A field is missing or not a valid public https link; the message names it."},"401":{"description":"Missing or unrecognised key."}}}},"/parse/tasks/{task_id}":{"get":{"tags":["Async lane"],"summary":"Status and result of a parse task","description":"Readable with the same key that created the task, for as long as we keep it — even if every callback delivery failed. Never returns the callback secret or URL.","x-served-by":"gateway","parameters":[{"name":"task_id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"The task.","content":{"application/json":{"schema":{"type":"object","properties":{"task_id":{"type":"string","format":"uuid"},"op":{"type":"string","description":"Which operation this task runs."},"status":{"type":"string","enum":["queued","processing","succeeded","failed"]},"status_code":{"type":["integer","null"],"description":"HTTP status the operation itself produced, once finished."},"result":{"description":"The operation's response body once `status` is `succeeded`; null before."},"error":{"type":["string","null"]},"delivery":{"type":"object","description":"Callback delivery. `not_requested` when no callback_url was given; `pending` → `delivered`, or `dead` after 6 attempts over ~17 h (1m, 5m, 15m, 1h, 4h, 12h; 15 s per attempt; any non-2xx counts as a failure; redirects are not followed). The result stays readable here either way.","properties":{"status":{"type":"string","enum":["not_requested","pending","delivered","dead"]},"attempts":{"type":"integer"}}},"created_at":{"type":"string","format":"date-time"},"completed_at":{"type":["string","null"],"format":"date-time"}},"required":["task_id","op","status","delivery","created_at"]}}}},"404":{"description":"Unknown task id, or a task another key created."},"401":{"description":"Missing or unrecognised key."}}}},"/evaluate/async":{"post":{"tags":["Async lane"],"summary":"Evaluate a backlog of CVs against a job, from links","description":"Answers **202** at once with a `task_id`; the work runs on our side. One `result` item per link, in order, same shape as `POST /evaluate/`. Poll `GET /evaluate/tasks/{task_id}`, or give a `callback_url` and we POST the finished task there, signed. A task that fails is never billed. Served by the API gateway; same `Authorization: Bearer key_…` as every other call.","x-served-by":"gateway","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"resume_urls":{"type":"array","minItems":1,"maxItems":10,"items":{"type":"string","format":"uri"},"description":"Public https links to the PDF or DOCX résumés. Fetched by us; not uploaded."},"job_details":{"type":"string","maxLength":200000,"description":"The job, as text. Or send `job_id` from `POST /jobs/`."},"job_id":{"type":"string","maxLength":255},"language":{"type":"string","maxLength":16},"callback_url":{"type":"string","format":"uri","maxLength":2048,"description":"Optional. https only, publicly reachable (private addresses are refused at delivery time), no credentials in the URL. Omit it and collect the result with GET /{op}/tasks/{task_id}."}},"required":["resume_urls"]}}}},"responses":{"202":{"description":"Accepted.","content":{"application/json":{"schema":{"type":"object","properties":{"task_id":{"type":"string","format":"uuid"},"status":{"type":"string","enum":["queued"]},"callback_secret":{"type":"string","description":"Only when callback_url was given. `whsec_…`, shown exactly once: HMAC-SHA256 key for `X-Curriculo-Signature: sha256=<hex>` over the raw callback body."}},"required":["task_id","status"]}}}},"400":{"description":"A field is missing or not a valid public https link; the message names it."},"401":{"description":"Missing or unrecognised key."}}}},"/evaluate/tasks/{task_id}":{"get":{"tags":["Async lane"],"summary":"Status and result of a evaluate task","description":"Readable with the same key that created the task, for as long as we keep it — even if every callback delivery failed. Never returns the callback secret or URL.","x-served-by":"gateway","parameters":[{"name":"task_id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"The task.","content":{"application/json":{"schema":{"type":"object","properties":{"task_id":{"type":"string","format":"uuid"},"op":{"type":"string","description":"Which operation this task runs."},"status":{"type":"string","enum":["queued","processing","succeeded","failed"]},"status_code":{"type":["integer","null"],"description":"HTTP status the operation itself produced, once finished."},"result":{"description":"The operation's response body once `status` is `succeeded`; null before."},"error":{"type":["string","null"]},"delivery":{"type":"object","description":"Callback delivery. `not_requested` when no callback_url was given; `pending` → `delivered`, or `dead` after 6 attempts over ~17 h (1m, 5m, 15m, 1h, 4h, 12h; 15 s per attempt; any non-2xx counts as a failure; redirects are not followed). The result stays readable here either way.","properties":{"status":{"type":"string","enum":["not_requested","pending","delivered","dead"]},"attempts":{"type":"integer"}}},"created_at":{"type":"string","format":"date-time"},"completed_at":{"type":["string","null"],"format":"date-time"}},"required":["task_id","op","status","delivery","created_at"]}}}},"404":{"description":"Unknown task id, or a task another key created."},"401":{"description":"Missing or unrecognised key."}}}},"/summary/async":{"post":{"tags":["Async lane"],"summary":"Summarize an interview recording from a link — up to 2 hours of audio or video","description":"Answers **202** at once with a `task_id`; the work runs on our side. `result` has the same shape as `POST /summary/` with a recording: transcript_text, transcript_entries, summary. Poll `GET /summary/tasks/{task_id}`, or give a `callback_url` and we POST the finished task there, signed. A task that fails is never billed. Served by the API gateway; same `Authorization: Bearer key_…` as every other call.","x-served-by":"gateway","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"media_url":{"type":"string","format":"uri","maxLength":2048,"description":"Public https link to the recording (mp3, mp4, wav, m4a, mov, webm, …)."},"interview_id":{"type":"string","maxLength":255,"description":"Optional label, echoed back unchanged."},"language":{"type":"string","maxLength":16,"description":"ISO 639-1 code for the summary prose; omit for English."},"callback_url":{"type":"string","format":"uri","maxLength":2048,"description":"Optional. https only, publicly reachable (private addresses are refused at delivery time), no credentials in the URL. Omit it and collect the result with GET /{op}/tasks/{task_id}."}},"required":["media_url"]}}}},"responses":{"202":{"description":"Accepted.","content":{"application/json":{"schema":{"type":"object","properties":{"task_id":{"type":"string","format":"uuid"},"status":{"type":"string","enum":["queued"]},"callback_secret":{"type":"string","description":"Only when callback_url was given. `whsec_…`, shown exactly once: HMAC-SHA256 key for `X-Curriculo-Signature: sha256=<hex>` over the raw callback body."}},"required":["task_id","status"]}}}},"400":{"description":"A field is missing or not a valid public https link; the message names it."},"401":{"description":"Missing or unrecognised key."}}}},"/summary/tasks/{task_id}":{"get":{"tags":["Async lane"],"summary":"Status and result of a summary task","description":"Readable with the same key that created the task, for as long as we keep it — even if every callback delivery failed. Never returns the callback secret or URL.","x-served-by":"gateway","parameters":[{"name":"task_id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"The task.","content":{"application/json":{"schema":{"type":"object","properties":{"task_id":{"type":"string","format":"uuid"},"op":{"type":"string","description":"Which operation this task runs."},"status":{"type":"string","enum":["queued","processing","succeeded","failed"]},"status_code":{"type":["integer","null"],"description":"HTTP status the operation itself produced, once finished."},"result":{"description":"The operation's response body once `status` is `succeeded`; null before."},"error":{"type":["string","null"]},"delivery":{"type":"object","description":"Callback delivery. `not_requested` when no callback_url was given; `pending` → `delivered`, or `dead` after 6 attempts over ~17 h (1m, 5m, 15m, 1h, 4h, 12h; 15 s per attempt; any non-2xx counts as a failure; redirects are not followed). The result stays readable here either way.","properties":{"status":{"type":"string","enum":["not_requested","pending","delivered","dead"]},"attempts":{"type":"integer"}}},"created_at":{"type":"string","format":"date-time"},"completed_at":{"type":["string","null"],"format":"date-time"}},"required":["task_id","op","status","delivery","created_at"]}}}},"404":{"description":"Unknown task id, or a task another key created."},"401":{"description":"Missing or unrecognised key."}}}},"/transcribe/async":{"post":{"tags":["Async lane"],"summary":"Transcribe a recording from a link without generating a summary","description":"Answers **202** at once with a `task_id`; the work runs on our side. `result` contains transcript_text and transcript_entries. Entries are empty when the backend supplies no timestamps. Poll `GET /transcribe/tasks/{task_id}`, or give a `callback_url` and we POST the finished task there, signed. A task that fails is never billed. Served by the API gateway; same `Authorization: Bearer key_…` as every other call.","x-served-by":"gateway","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"media_url":{"type":"string","format":"uri","maxLength":2048,"description":"Public https link to the recording (mp3, mp4, wav, m4a, mov, webm, …)."},"language":{"type":"string","maxLength":16,"description":"ISO 639-1 code for the summary prose; omit for English."},"callback_url":{"type":"string","format":"uri","maxLength":2048,"description":"Optional. https only, publicly reachable (private addresses are refused at delivery time), no credentials in the URL. Omit it and collect the result with GET /{op}/tasks/{task_id}."}},"required":["media_url"]}}}},"responses":{"202":{"description":"Accepted.","content":{"application/json":{"schema":{"type":"object","properties":{"task_id":{"type":"string","format":"uuid"},"status":{"type":"string","enum":["queued"]},"callback_secret":{"type":"string","description":"Only when callback_url was given. `whsec_…`, shown exactly once: HMAC-SHA256 key for `X-Curriculo-Signature: sha256=<hex>` over the raw callback body."}},"required":["task_id","status"]}}}},"400":{"description":"A field is missing or not a valid public https link; the message names it."},"401":{"description":"Missing or unrecognised key."}}}},"/transcribe/tasks/{task_id}":{"get":{"tags":["Async lane"],"summary":"Status and result of a transcribe task","description":"Readable with the same key that created the task, for as long as we keep it — even if every callback delivery failed. Never returns the callback secret or URL.","x-served-by":"gateway","parameters":[{"name":"task_id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"The task.","content":{"application/json":{"schema":{"type":"object","properties":{"task_id":{"type":"string","format":"uuid"},"op":{"type":"string","description":"Which operation this task runs."},"status":{"type":"string","enum":["queued","processing","succeeded","failed"]},"status_code":{"type":["integer","null"],"description":"HTTP status the operation itself produced, once finished."},"result":{"description":"The operation's response body once `status` is `succeeded`; null before."},"error":{"type":["string","null"]},"delivery":{"type":"object","description":"Callback delivery. `not_requested` when no callback_url was given; `pending` → `delivered`, or `dead` after 6 attempts over ~17 h (1m, 5m, 15m, 1h, 4h, 12h; 15 s per attempt; any non-2xx counts as a failure; redirects are not followed). The result stays readable here either way.","properties":{"status":{"type":"string","enum":["not_requested","pending","delivered","dead"]},"attempts":{"type":"integer"}}},"created_at":{"type":"string","format":"date-time"},"completed_at":{"type":["string","null"],"format":"date-time"}},"required":["task_id","op","status","delivery","created_at"]}}}},"404":{"description":"Unknown task id, or a task another key created."},"401":{"description":"Missing or unrecognised key."}}}},"/translate/async":{"post":{"tags":["Async lane"],"summary":"Translate text or documents without holding the connection open","description":"Answers **202** at once with a `task_id`; the work runs on our side. `result` has the same shape as `POST /translate/`. Provide exactly one of `text`, `texts`, or `file_urls`. Poll `GET /translate/tasks/{task_id}`, or give a `callback_url` and we POST the finished task there, signed. A task that fails is never billed. Served by the API gateway; same `Authorization: Bearer key_…` as every other call.","x-served-by":"gateway","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"text":{"type":"string","maxLength":50000,"description":"One string. Send this, `texts`, or `file_urls`."},"texts":{"type":"array","maxItems":200,"items":{"type":"string","maxLength":50000},"description":"Several strings, in order. Send this, `text`, or `file_urls`."},"file_urls":{"type":"array","minItems":1,"maxItems":10,"items":{"type":"string","format":"uri"},"description":"Public https links to the PDF or DOCX documents to translate. Fetched by us; not uploaded."},"source_language":{"type":"string","maxLength":16,"description":"ISO 639-1 code of the input, e.g. `en`."},"target_language":{"type":"string","maxLength":16,"description":"ISO 639-1 code to translate into, e.g. `fr`."},"callback_url":{"type":"string","format":"uri","maxLength":2048,"description":"Optional. https only, publicly reachable (private addresses are refused at delivery time), no credentials in the URL. Omit it and collect the result with GET /{op}/tasks/{task_id}."}},"required":["source_language","target_language"]}}}},"responses":{"202":{"description":"Accepted.","content":{"application/json":{"schema":{"type":"object","properties":{"task_id":{"type":"string","format":"uuid"},"status":{"type":"string","enum":["queued"]},"callback_secret":{"type":"string","description":"Only when callback_url was given. `whsec_…`, shown exactly once: HMAC-SHA256 key for `X-Curriculo-Signature: sha256=<hex>` over the raw callback body."}},"required":["task_id","status"]}}}},"400":{"description":"A field is missing or not a valid public https link; the message names it."},"401":{"description":"Missing or unrecognised key."}}}},"/translate/tasks/{task_id}":{"get":{"tags":["Async lane"],"summary":"Status and result of a translate task","description":"Readable with the same key that created the task, for as long as we keep it — even if every callback delivery failed. Never returns the callback secret or URL.","x-served-by":"gateway","parameters":[{"name":"task_id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"The task.","content":{"application/json":{"schema":{"type":"object","properties":{"task_id":{"type":"string","format":"uuid"},"op":{"type":"string","description":"Which operation this task runs."},"status":{"type":"string","enum":["queued","processing","succeeded","failed"]},"status_code":{"type":["integer","null"],"description":"HTTP status the operation itself produced, once finished."},"result":{"description":"The operation's response body once `status` is `succeeded`; null before."},"error":{"type":["string","null"]},"delivery":{"type":"object","description":"Callback delivery. `not_requested` when no callback_url was given; `pending` → `delivered`, or `dead` after 6 attempts over ~17 h (1m, 5m, 15m, 1h, 4h, 12h; 15 s per attempt; any non-2xx counts as a failure; redirects are not followed). The result stays readable here either way.","properties":{"status":{"type":"string","enum":["not_requested","pending","delivered","dead"]},"attempts":{"type":"integer"}}},"created_at":{"type":"string","format":"date-time"},"completed_at":{"type":["string","null"],"format":"date-time"}},"required":["task_id","op","status","delivery","created_at"]}}}},"404":{"description":"Unknown task id, or a task another key created."},"401":{"description":"Missing or unrecognised key."}}}},"/prompt/resumes":{"get":{"tags":["Prompt resumes"],"summary":"List your account's saved resume contexts","x-served-by":"gateway","description":"Console keys only. Includes the original account resume and mapped end users, never another account's records. No AI charge or prepaid balance required. Browsing never creates a record.","security":[{"HTTPBearer":[]}],"parameters":[{"name":"search","in":"query","description":"Case-insensitive partial match on name, external_user_id, or resume_id.","schema":{"type":"string","minLength":1,"maxLength":255}},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":100,"default":50}},{"name":"offset","in":"query","schema":{"type":"integer","minimum":0,"maximum":1000000,"default":0}},{"name":"cursor","in":"query","description":"Stable continuation token from next_cursor. Prefer this over offset when records may be created while browsing.","schema":{"type":"string","minLength":1,"maxLength":1024}}],"responses":{"200":{"description":"Account-owned saved data.","content":{"application/json":{"schema":{"type":"object","properties":{"items":{"type":"array","items":{"type":"object","required":["external_user_id","customer_id","resume_id","version"],"properties":{"external_user_id":{"type":["string","null"],"description":"Null for the original account context; otherwise reuse in X-Curriculo-User-Id."},"customer_id":{"type":"string"},"resume_id":{"type":"string"},"name":{"type":["string","null"]},"version":{"type":"integer"},"updated_at":{"type":"string","format":"date-time"}}}},"next_cursor":{"type":["string","null"],"description":"Pass as cursor for the next stable page; null means finished."},"next_offset":{"type":["integer","null"],"description":"Legacy offset continuation; new clients should use next_cursor."}}}}}},"401":{"description":"Invalid or missing key."},"403":{"description":"Account suspended/revoked or legacy token."},"404":{"description":"Unknown or unowned resume."},"422":{"description":"Invalid query parameters."}}}},"/prompt/resume":{"get":{"tags":["Prompt resumes"],"summary":"Retrieve a saved resume from your account","x-served-by":"gateway","description":"Console keys only. Includes the original account resume and mapped end users, never another account's records. No AI charge or prepaid balance required. Browsing never creates a record.","security":[{"HTTPBearer":[]}],"parameters":[{"name":"resume_id","in":"query","required":true,"schema":{"type":"string","minLength":1,"maxLength":255}}],"responses":{"200":{"description":"Account-owned saved data.","content":{"application/json":{"schema":{"type":"object","required":["external_user_id","customer_id","resume_id","version"],"properties":{"external_user_id":{"type":["string","null"],"description":"Null for the original account context; otherwise reuse in X-Curriculo-User-Id."},"customer_id":{"type":"string"},"resume_id":{"type":"string"},"name":{"type":["string","null"]},"version":{"type":"integer"},"updated_at":{"type":"string","format":"date-time"},"ai_data":{"description":"Saved content from the latest active resume version."}}}}}},"401":{"description":"Invalid or missing key."},"403":{"description":"Account suspended/revoked or legacy token."},"404":{"description":"Unknown or unowned resume."},"422":{"description":"Invalid query parameters."}}}}},"components":{"schemas":{"AiResponse":{"properties":{"language":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Language","description":"Language the résumé content is currently in (ISO 639-1).","examples":["en"]},"data":{"anyOf":[{"items":{"$ref":"#/components/schemas/ResumeSegment"},"type":"array"},{"type":"null"}],"title":"Data","description":"The résumé as an ordered list of segments."},"changes":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Changes","description":"Human-readable summary of what changed in this call."},"total_cost":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Total Cost","description":"Model cost for this call, in USD."}},"additionalProperties":true,"type":"object","title":"AiResponse","description":"The updated résumé, returned when an edit/add/translate changed it."},"Body_evaluate_evaluate__post":{"properties":{"resume_pdfs":{"items":{"type":"string","format":"binary"},"type":"array","title":"Resume Pdfs","description":"The candidates' CVs (PDF), up to 10 MB each. Send one file or up to 10 in a single request; every CV is evaluated against the same job.","default":[]},"resume_pdf":{"anyOf":[{"type":"string","format":"binary"},{"type":"null"}],"title":"Resume Pdf","description":"Single-document alias for `resume_pdfs`, kept for existing integrations."},"job_details":{"type":"string","title":"Job Details","description":"The job description, as text pasted from your careers page — this is the normal way to send it. A JSON object is accepted if you already hold structured requirements. Omit it only when you send `job_file` or `job_id` instead.","default":""},"job_file":{"anyOf":[{"type":"string","format":"binary"},{"type":"null"}],"title":"Job File","description":"The job description as a document (PDF or DOCX), for clients whose JD lives in a file rather than a string."},"job_id":{"type":"string","title":"Job Id","description":"Optional. A job registered earlier via `POST /jobs/`, sent instead of repeating `job_details` across a backlog. Never required — sending the description itself always works.","default":""},"language":{"type":"string","title":"Language","description":"Optional ISO 639-1 code to render the candidate-facing prose in (e.g. `ko`); empty = English.","default":""}},"type":"object","title":"Body_evaluate_evaluate__post"},"Body_parse_parse__post":{"properties":{"files":{"items":{"type":"string","format":"binary"},"type":"array","title":"Files","description":"The résumés to read — PDF or DOCX, up to 10 MB each. Send one file or up to 10 in a single request.","default":[]},"file":{"anyOf":[{"type":"string","format":"binary"},{"type":"null"}],"title":"File","description":"Single-document alias for `files`, kept for existing integrations."}},"type":"object","title":"Body_parse_parse__post"},"Body_prompt_prompt__post":{"properties":{"prompt_text":{"type":"string","title":"Prompt Text","description":"Your instruction or question, in plain language. May be written in **any** language. Examples: *'add Python to my skills'*, *'make my summary more concise'*, *'what is my most recent job?'*.","examples":["make my resume more professional"]},"language":{"type":"string","title":"Language","description":"Optional ISO 639-1 code (e.g. `ko`, `ja`, `fr`) to render the résumé in that language. Omit to keep the source language. You do **not** ask for translation in `prompt_text` — set this field.","default":"","examples":["ko"]},"template_id":{"type":"string","title":"Template Id","description":"Optional template identifier; echoed back in the response.","default":"default"},"file":{"type":"string","format":"binary","title":"File","description":"Optional PDF (max 10 MB). Attach it on your **first** request to seed your résumé from an existing CV; later calls edit that same résumé and don't need a file."}},"type":"object","required":["prompt_text"],"title":"Body_prompt_prompt__post"},"Body_transcribe_transcribe__post":{"properties":{"media":{"type":"string","format":"binary","title":"Media","description":"One audio or video recording."},"language":{"type":"string","title":"Language","description":"Optional ISO 639-1 language hint.","default":""}},"type":"object","required":["media"],"title":"Body_transcribe_transcribe__post"},"CertificationEntry":{"properties":{"sub_segment_data":{"$ref":"#/components/schemas/CertificationItem","description":"The certification entry payload."}},"additionalProperties":true,"type":"object","required":["sub_segment_data"],"title":"CertificationEntry","description":"One item of the **Licenses & Certifications** segment's list."},"CertificationItem":{"properties":{"title":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Title","description":"Certification name."},"text":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Text","description":"Description, if any."},"date":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Date","description":"Issue date / year."},"organization":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Organization","description":"Issuing organization."}},"additionalProperties":true,"type":"object","title":"CertificationItem","description":"`sub_segment_data` of one **Licenses & Certifications** entry."},"CompanyInfo":{"properties":{"name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Name","description":"Company / employer name."},"title":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Title","description":"Job title / role."},"start_date":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Start Date","description":"Start date, e.g. `Aug 2024`."},"end_date":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"End Date","description":"End date, or `present`."},"location":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Location","description":"Work location, if given."}},"additionalProperties":true,"type":"object","title":"CompanyInfo","description":"The employer/role header of one **Experience** entry."},"DetectLanguageResponse":{"properties":{"language":{"type":"string","title":"Language"},"confidence":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Confidence"}},"type":"object","required":["language"],"title":"DetectLanguageResponse"},"EducationEntry":{"properties":{"sub_segment_data":{"$ref":"#/components/schemas/EducationItem","description":"The education entry payload."}},"additionalProperties":true,"type":"object","required":["sub_segment_data"],"title":"EducationEntry","description":"One item of the **Education** segment's list."},"EducationItem":{"properties":{"institution_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Institution Name","description":"School / university name."},"degree":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Degree","description":"Degree, e.g. `B.Sc. Computer Science`."},"field_of_study":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Field Of Study","description":"Field / major."},"start_date":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Start Date","description":"Start date / year."},"end_date":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"End Date","description":"End date / year."},"location":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Location","description":"Location, if given."},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description","description":"Free-text description, if given."},"gpa":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Gpa","description":"GPA, if given."}},"additionalProperties":true,"type":"object","title":"EducationItem","description":"`sub_segment_data` of one **Education** entry."},"ExperienceEntry":{"properties":{"sub_segment_data":{"$ref":"#/components/schemas/ExperienceItem","description":"The experience entry payload."}},"additionalProperties":true,"type":"object","required":["sub_segment_data"],"title":"ExperienceEntry","description":"One item of the **Experience** segment's list."},"ExperienceItem":{"properties":{"company_info":{"anyOf":[{"$ref":"#/components/schemas/CompanyInfo"},{"type":"null"}],"description":"Employer / role header."},"responsibilities":{"anyOf":[{"items":{"$ref":"#/components/schemas/Responsibility"},"type":"array"},{"type":"null"}],"title":"Responsibilities","description":"List of responsibility / achievement bullets."},"skills":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Skills","description":"Comma-separated skills used in this role."}},"additionalProperties":true,"type":"object","title":"ExperienceItem","description":"`sub_segment_data` of one **Experience** entry."},"HTTPValidationError":{"properties":{"detail":{"items":{"$ref":"#/components/schemas/ValidationError"},"type":"array","title":"Detail"}},"type":"object","title":"HTTPValidationError"},"ParsedAddress":{"properties":{"street":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Street","description":"Street address."},"city":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"City","description":"City."},"state":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"State","description":"State / region / province."},"country":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Country","description":"Country."},"postal_code":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Postal Code","description":"Postal / ZIP code."}},"additionalProperties":true,"type":"object","title":"ParsedAddress","description":"The `address` object."},"ParsedEducation":{"properties":{"degree":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Degree","description":"Full degree / diploma / certificate name."},"university":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"University","description":"Institution name."},"field_of_study":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Field Of Study","description":"Field of study."},"graduation_year":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Graduation Year","description":"Graduation year."},"start_date":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Start Date","description":"Start date."},"end_date":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"End Date","description":"End date."},"location":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Location","description":"Institution location."},"gpa":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Gpa","description":"GPA, grade, percentage or class."},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description","description":"Coursework, honours, thesis, research."}},"additionalProperties":true,"type":"object","title":"ParsedEducation","description":"One entry of `education`."},"ParsedExperience":{"properties":{"company":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Company","description":"Organization / employer name."},"job_title":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Job Title","description":"Position / role title."},"start_date":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Start Date","description":"Start date."},"end_date":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"End Date","description":"End date, or the résumé's own word for *present* in its own language (e.g. `الحاضر`, `至今`, `actuel`)."},"duration":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Duration","description":"Human-readable duration."},"location":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Location","description":"Work location."},"description":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Description","description":"Responsibility / achievement bullets, one per item."}},"additionalProperties":true,"type":"object","title":"ParsedExperience","description":"One entry of `experience` (work, internship, clinical, freelance, military…)."},"ParsedProject":{"properties":{"name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Name","description":"Project name."},"description":{"anyOf":[{"type":"string"},{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Description","description":"Description — a string or a list of bullets."},"tools":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Tools","description":"Tools / technologies / methods used."},"role":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Role","description":"Role held on the project."},"duration":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Duration","description":"Duration, if mentioned."}},"additionalProperties":true,"type":"object","title":"ParsedProject","description":"One entry of `projects`."},"ParsedResume":{"properties":{"name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Name","description":"Full name."},"title":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Title","description":"Current or most recent professional title."},"email":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Email","description":"Email address."},"phone":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Phone","description":"Phone number."},"github":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Github","description":"GitHub URL, if present."},"linkedin":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Linkedin","description":"LinkedIn URL, if present."},"social_media":{"anyOf":[{"items":{},"type":"array"},{"type":"null"}],"title":"Social Media","description":"Other profile links (portfolio, ORCID, personal site…)."},"address":{"anyOf":[{"$ref":"#/components/schemas/ParsedAddress"},{"type":"null"}],"description":"Structured address."},"summary":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Summary","description":"Professional summary / objective."},"education":{"anyOf":[{"items":{"$ref":"#/components/schemas/ParsedEducation"},"type":"array"},{"type":"null"}],"title":"Education","description":"All education entries."},"experience":{"anyOf":[{"items":{"$ref":"#/components/schemas/ParsedExperience"},"type":"array"},{"type":"null"}],"title":"Experience","description":"All experience entries."},"technical_skills":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Technical Skills","description":"Hard skills, tools and technologies found anywhere in the résumé."},"soft_skills":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Soft Skills","description":"Soft / interpersonal skills."},"licenses_and_certifications":{"anyOf":[{"items":{},"type":"array"},{"type":"null"}],"title":"Licenses And Certifications","description":"Licences, certifications and professional credentials."},"achievements":{"anyOf":[{"items":{},"type":"array"},{"type":"null"}],"title":"Achievements","description":"Awards, honours, publications, patents, grants."},"projects":{"anyOf":[{"items":{"$ref":"#/components/schemas/ParsedProject"},"type":"array"},{"type":"null"}],"title":"Projects","description":"Projects."},"languages":{"anyOf":[{"items":{},"type":"array"},{"type":"null"}],"title":"Languages","description":"Spoken languages and proficiency."},"publications":{"anyOf":[{"items":{},"type":"array"},{"type":"null"}],"title":"Publications","description":"Papers, articles, books."},"volunteer_experience":{"anyOf":[{"items":{},"type":"array"},{"type":"null"}],"title":"Volunteer Experience","description":"Community service, pro bono and nonprofit work."},"additional_information":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Additional Information","description":"Any other section found, keyed by its own heading (military service, clearances, memberships, interests, references…)."}},"additionalProperties":true,"type":"object","title":"ParsedResume","description":"The structured résumé returned by ``POST /parse/``.\n\nEvery value is extracted **in the résumé's own language and script** — the\nparser never translates or transliterates.\n\nA field the résumé does not contain comes back empty (``\"\"`` / ``[]`` /\n``{}``) rather than absent. That is guaranteed for the list fields\n``ai/main.py`` coerces — ``education``, ``experience``, ``technical_skills``,\n``soft_skills``, ``projects``, ``achievements``, ``languages``,\n``social_media`` — which are always arrays. Everything else relies on the\nextractor prompt honouring it, so callers should read the rarer sections\ndefensively rather than assuming the key is present.","examples":[{"address":{"city":"London","country":"UK"},"education":[{"degree":"B.Sc. Computer Science","graduation_year":"2016","university":"University of London"}],"email":"ada@example.com","experience":[{"company":"Acme","description":["Led the billing rewrite."],"end_date":"Present","job_title":"Senior Engineer","start_date":"2021"}],"languages":["English","French"],"linkedin":"https://linkedin.com/in/ada","name":"Ada Lovelace","phone":"+1 555 0100","soft_skills":["Mentoring"],"summary":"Engineer with 8 years building distributed systems.","technical_skills":["Python","PostgreSQL","Kubernetes"],"title":"Senior Software Engineer"}]},"PersonalInformationData":{"properties":{"name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Name","description":"Full name."},"email":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Email","description":"Email address."},"phone":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Phone","description":"Phone number."},"location":{"anyOf":[{"$ref":"#/components/schemas/ResumeLocation"},{"type":"null"}],"description":"Location object."},"linkedin":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Linkedin","description":"LinkedIn profile URL or handle."},"github":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Github","description":"GitHub profile URL or handle."}},"additionalProperties":true,"type":"object","title":"PersonalInformationData","description":"`segment_data` of the **Personal Information** segment."},"PublicApiError":{"properties":{"detail":{"type":"string","title":"Detail","description":"Human-readable explanation of why the request was rejected.","examples":["Invalid API token."]}},"type":"object","required":["detail"],"title":"PublicApiError","description":"Standard error envelope for every non-2xx response."},"PublicDetectLanguageRequest":{"properties":{"text":{"type":"string","title":"Text","description":"A single text to inspect, up to 50,000 characters.","default":"","examples":["Bonjour, je suis développeur backend."]},"texts":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Texts","description":"Several texts to inspect in one call, up to 200 items. The response keeps your order, one result per item.","examples":[["Bonjour tout le monde","안녕하세요"]]},"default_language":{"type":"string","title":"Default Language","description":"Returned when a text is too short or too mixed to call.","default":"en","examples":["en"]}},"type":"object","title":"PublicDetectLanguageRequest","description":"Body for ``POST /detect-language/`` — one text or a list of them."},"PublicJobRequest":{"properties":{"job_details":{"type":"string","title":"Job Details","description":"The job. Send it as plain text — paste the description straight from your careers page — or as a JSON object if you already hold structured requirements. Structured input additionally enables an explicit must-have / preferred checklist in the evaluation; plain text is assessed holistically.","examples":["Senior backend engineer. Python and FastAPI, 5+ years, Postgres. Kubernetes is a plus. Based in Seoul.","{\"must_have_skills\": [\"Python\", \"FastAPI\"], \"seniority\": \"senior\"}"]},"language":{"type":"string","title":"Language","description":"Optional ISO 639-1 default for the candidate-facing prose.","default":"","examples":["ko"]},"label":{"type":"string","title":"Label","description":"Your own name for the job, echoed back.","default":"","examples":["Backend engineer, Seoul"]}},"type":"object","required":["job_details"],"title":"PublicJobRequest","description":"Body for ``POST /jobs/``."},"PublicJobResponse":{"properties":{"job_id":{"type":"string","title":"Job Id","description":"Send this as `job_id` on /evaluate/."},"label":{"type":"string","title":"Label","description":"Echoes the label you registered.","default":""}},"type":"object","required":["job_id"],"title":"PublicJobResponse","description":"Response for ``POST /jobs/``."},"PublicPromptResponse":{"properties":{"customer_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Customer Id","description":"Internal customer ID returned by gateway prompts using an end-user or target resume selector."},"resume_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Resume Id","description":"Internal resume context ID returned by gateway prompts using an end-user or target resume selector."},"mode":{"type":"string","title":"Mode","description":"What the request did. One of `qa` (a question was answered), `edit` / `addon` (the résumé was changed), or `qa_with_modification` (answered *and* changed).","examples":["qa","edit","addon","qa_with_modification"]},"assistant_message":{"type":"string","title":"Assistant Message","description":"Natural-language reply to show the user, rendered in the résumé's language (or the requested `language`).","examples":["I've updated your resume."]},"ai_response":{"anyOf":[{"$ref":"#/components/schemas/AiResponse"},{"type":"null"}],"description":"Present only when the résumé changed. The updated résumé as segment JSON under `data`, plus `language`, a `changes` summary and `total_cost`. Omitted for pure question (`qa`) responses."}},"additionalProperties":true,"type":"object","required":["mode","assistant_message"],"title":"PublicPromptResponse","description":"The result of a ``POST /prompt/`` call.\n\nShape depends on what your instruction did:\n\n* **Question** (e.g. *\"what's my most recent role?\"*) → ``mode = \"qa\"`` and a\n  natural-language ``assistant_message``; ``ai_response`` is omitted.\n* **Edit / add** (e.g. *\"add Python to my skills\"*, *\"make it more\n  professional\"*, or a translation) → ``mode`` is ``\"edit\"``, ``\"addon\"`` or\n  ``\"qa_with_modification\"`` and ``ai_response`` carries the updated résumé.\n\nExtra fields may be present and are passed through unchanged.","examples":[{"assistant_message":"Your most recent role is Senior Engineer at Acme (2021–present).","mode":"qa"},{"ai_response":{"changes":["Added skill: Python"],"data":[{"segment_data":[{"sub_segment_data":{"categories":[{"text":"Python, TypeScript","title":"Languages"}],"title":"Technical Skills"}}],"segment_id":"462ccb37-dc50-5f4c-86e0-5b7c9071fe8d","segment_name":"Skills"}],"language":"en","total_cost":0.0012},"assistant_message":"I've updated your resume.","mode":"edit"}]},"PublicSingleTranslateResponse":{"properties":{"translation":{"type":"string","title":"Translation","description":"Translated text."},"target_language":{"type":"string","title":"Target Language","description":"Normalized target language code."},"source_language":{"type":"string","title":"Source Language","description":"Normalized source language code."},"ok":{"type":"boolean","title":"Ok","description":"False when every translation engine failed and `translation` is the original source text."}},"type":"object","required":["translation","target_language","source_language","ok"],"title":"PublicSingleTranslateResponse","description":"Response when the request uses singular ``text``."},"PublicTranscribeResponse":{"properties":{"transcript_text":{"type":"string","title":"Transcript Text"},"transcript_entries":{"items":{"additionalProperties":true,"type":"object"},"type":"array","title":"Transcript Entries"}},"type":"object","required":["transcript_text","transcript_entries"],"title":"PublicTranscribeResponse"},"Responsibility":{"properties":{"text":{"type":"string","title":"Text","description":"One responsibility / achievement bullet."}},"additionalProperties":true,"type":"object","required":["text"],"title":"Responsibility","description":"A single bullet under an Experience entry's `responsibilities`."},"ResumeLocation":{"properties":{"city":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"City","description":"City, rendered in the output language."},"state":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"State","description":"State / region / province."},"country":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Country","description":"Country."},"street":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Street","description":"Street address, when present."},"postal_code":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Postal Code","description":"Postal / ZIP code, when present."}},"additionalProperties":true,"type":"object","title":"ResumeLocation","description":"A geographic location (used by Personal Information and work entries)."},"ResumeSegment":{"properties":{"segment_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Segment Id","description":"Stable identifier for this segment."},"segment_name":{"type":"string","title":"Segment Name","description":"Section name, e.g. `Personal Information`, `Experience`, `Skills`.","examples":["Experience"]},"segment_data":{"anyOf":[{"$ref":"#/components/schemas/PersonalInformationData"},{"type":"string"},{"items":{"$ref":"#/components/schemas/ExperienceEntry"},"type":"array"},{"items":{"$ref":"#/components/schemas/EducationEntry"},"type":"array"},{"items":{"$ref":"#/components/schemas/SkillsEntry"},"type":"array"},{"items":{"$ref":"#/components/schemas/CertificationEntry"},"type":"array"},{"items":{"additionalProperties":true,"type":"object"},"type":"array"}],"title":"Segment Data","description":"The section payload; shape depends on `segment_name` (see table above)."}},"additionalProperties":true,"type":"object","required":["segment_name","segment_data"],"title":"ResumeSegment","description":"One section of the résumé.\n\n``segment_data`` is **polymorphic** — its shape depends on ``segment_name``:\n\n| ``segment_name``            | ``segment_data`` |\n|-----------------------------|------------------|\n| Personal Information        | object (`PersonalInformationData`) |\n| Professional Summary        | string |\n| Experience                  | list of `ExperienceEntry` |\n| Education                   | list of `EducationEntry` |\n| Skills                      | list of `SkillsEntry` |\n| Licenses And Certifications | list of `CertificationEntry` |\n| Projects / Languages / Awards / References | list of section-specific items |"},"SkillCategory":{"properties":{"title":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Title","description":"Category name, e.g. `Languages`."},"text":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Text","description":"Comma-separated skills in this category."}},"additionalProperties":true,"type":"object","title":"SkillCategory","description":"A grouped skills category, e.g. `Languages: TypeScript, JavaScript`."},"SkillsEntry":{"properties":{"sub_segment_data":{"$ref":"#/components/schemas/SkillsItem","description":"The skills entry payload."}},"additionalProperties":true,"type":"object","required":["sub_segment_data"],"title":"SkillsEntry","description":"One item of the **Skills** segment's list."},"SkillsItem":{"properties":{"title":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Title","description":"Group title, e.g. `Technical Skills`."},"text":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Text","description":"Flat comma-separated skills (flat form)."},"categories":{"anyOf":[{"items":{"$ref":"#/components/schemas/SkillCategory"},"type":"array"},{"type":"null"}],"title":"Categories","description":"Grouped skill categories (grouped form)."}},"additionalProperties":true,"type":"object","title":"SkillsItem","description":"`sub_segment_data` of one **Skills** entry.\n\nEither a flat ``{title, text}`` (e.g. *Soft Skills*) or a grouped\n``{title, categories: [...]}`` (e.g. *Technical Skills*)."},"TranslateResponse":{"properties":{"translations":{"items":{"type":"string"},"type":"array","title":"Translations"},"target_language":{"type":"string","title":"Target Language"},"source_language":{"type":"string","title":"Source Language"},"recommended_async":{"type":"boolean","title":"Recommended Async","default":false},"ok":{"anyOf":[{"items":{"type":"boolean"},"type":"array"},{"type":"null"}],"title":"Ok"}},"type":"object","required":["translations","target_language","source_language"],"title":"TranslateResponse"},"ValidationError":{"properties":{"loc":{"items":{"anyOf":[{"type":"string"},{"type":"integer"}]},"type":"array","title":"Location"},"msg":{"type":"string","title":"Message"},"type":{"type":"string","title":"Error Type"}},"type":"object","required":["loc","msg","type"],"title":"ValidationError"}},"securitySchemes":{"HTTPBearer":{"type":"http","description":"Your Curriculo client API token.","scheme":"bearer"}}}}