Save an answer
const url = 'http://127.0.0.1:8765/api/answers';const options = { method: 'POST', headers: {'Content-Type': 'application/json'}, body: '{"actor":"agent","answer":"Yes, 4 years, GKE + BigQuery","question":"Do you have GCP experience?","question_id":"cloud:gcp","source":"from the user\'s repo infra-charts, at the user\'s request"}'};
try { const response = await fetch(url, options); const data = await response.json(); console.log(data);} catch (error) { console.error(error);}curl --request POST \ --url http://127.0.0.1:8765/api/answers \ --header 'Content-Type: application/json' \ --data '{ "actor": "agent", "answer": "Yes, 4 years, GKE + BigQuery", "question": "Do you have GCP experience?", "question_id": "cloud:gcp", "source": "from the user'\''s repo infra-charts, at the user'\''s request" }'Save an answer; with reassess the job is assessed again. Answers 201 with the saved answer. Storing it is local; the model runs only when reassess is given. A job has one assessment (0.1.11.9) and reassess replaces it. reassess.profile_id is optional and picks no record: it is the role recorded on the new assessment (left out: the selected role); an unknown id answers 404 profile_not_found before anything is saved. The answer is the user’s: every later assessment reuses it, for the same question id and for the same fact worded differently. A new id creates the answer; an existing id replaces its text (send revision to be safe against another writer: 409 revision_conflict carries the current answer). Text holding an email, phone, link or street address is refused with 422 personal_info_refused. Example, an agent saves a factual reply from a chat and the next posting that asks it is not asked again: POST this route with the request example; then POST /api/assess for another posting that requires GCP: the answer has no question for it and its resume_evidence reads Story bank cloud:gcp: .... 0.1.10.7: the write also queues the background pipeline (tailored resume, assessment against it, Scout ATS score, Scout label) for every job of an active profile whose stored assessment left open a question this answers; at most pipeline.auto_jobs_per_trigger (10) jobs run, the rest wait for an approval (GET /api/pipeline/approvals). The pipeline’s tailoring replaces only a tailored resume the pipeline itself made: one tailored on demand (POST /api/tailored-resumes) or with a line chosen or edited (PUT /api/tailored-resumes/lines) is kept as it is, its updated_at unchanged, and the assessment, the Scout ATS score and the Scout label are made against it. Read what was queued with GET /api/pipeline.
Request Bodyrequired
Section titled “Request Bodyrequired”object
Who writes: recorded as written_by. Also the X-GigAI-Actor header. Without either, a write from the Scout UI (a browser page of this server) is the operator’s and any other loopback write is the agent’s.
The answer.
When the answer confirms a bank_suggestions near match: that suggestion’s bank_question_id.
The question’s own words, kept with the answer.
The question’s id (<category>:<value>).
{"job_identity": "<id>", "profile_id": "<id>"}: a job to assess again with the answer (it has one assessment, which this replaces). profile_id is optional and picks no record: the role recorded on the new assessment (left out: the selected role).
object
The revision you read, when the answer exists; a stale one answers 409.
Free text, at most 300 characters: where the answer came from (e.g. “from the user’s repo, at the user’s request”). Returned with the answer; never sent to a model. A new answer text without it drops the stored one.
Your own tag (lowercase, at most 40 characters); omitted = a tag from the question.
Example
{ "actor": "agent", "answer": "Yes, 4 years, GKE + BigQuery", "question": "Do you have GCP experience?", "question_id": "cloud:gcp", "source": "from the user's repo infra-charts, at the user's request"}Responses
Section titled “Responses”Success.
object
Example
{ "answer": { "answer": "Yes, 4 years, GKE + BigQuery", "created_at": "2026-10-02T15:00:00.000000Z", "history": [ { "action": "answered", "at": "2026-10-02T15:00:00.000000Z", "by": "agent" } ], "jobs": [ { "at": "2026-10-02T15:00:00.000000Z", "company": "Acme", "job_identity": "https://boards.greenhouse.io/acme/jobs/101", "kind": "answered", "title": "Software Engineer", "url": "https://boards.greenhouse.io/acme/jobs/101" } ], "question": "Do you have GCP experience?", "question_id": "cloud:gcp", "revision": 1, "source": "from the user's repo infra-charts, at the user's request", "tag": "technical", "updated_at": "2026-10-02T15:00:00.000000Z", "written_by": "agent" }, "question_id": "cloud:gcp", "reassessed": null, "record_id": "rec_1", "revision_id": "rev_1", "schema_version": "scout-answers-response:1"}Forbidden / forbidden_origin: loopback peer and Host 127.0.0.1:<port> or localhost:<port> only (Origin too on writes).
object
object
Examplegenerated
{ "error": { "allowed_keys": [ "example" ], "code": "example", "message": "example" }}Reassess_not_found, profile_not_found, not_found, target_unavailable
object
object
Example
{ "error": { "code": "reassess_not_found", "message": "..." }}Revision_conflict
object
object
Example
{ "error": { "code": "revision_conflict", "message": "..." }}Unsupported_media_type: writes need Content-Type: application/json.
object
object
Examplegenerated
{ "error": { "allowed_keys": [ "example" ], "code": "example", "message": "example" }}Unknown_key, wrong_type, invalid_value, answer_invalid, personal_info_refused, reassess_unavailable
object
object
Example
{ "error": { "code": "unknown_key", "message": "..." }}