Custom questions
Your agent asks questions two ways: objectives configured on the agent (every call
of that version asks them), and per-call questions attached to a single
POST /v1/calls launch. Both record answers through the same tool, land in the same
SurveyResponse, and arrive in the same webhooks.
Objectives on the agent
Section titled “Objectives on the agent”Objectives live on the agent definition and freeze into each published version. A
scored question carries a scoring block:
{ "objectives": [ { "id": "csat_overall", "prompt": "How satisfied were you with your visit, one to five?", "scoring": { "scale": "csat", "mapping": { "1": 1, "2": 2, "3": 3, "4": 4, "5": 5 }, "weight": 1 } }, { "id": "would_return", "prompt": "Would you come back?", "scoring": { "scale": "ordinal", "points": 3, "mapping": { "no": 1, "maybe": 2, "yes": 3 } } }, { "id": "verbatim", "prompt": "Anything else you want us to know?" } ]}Four scales: csat (1–5), nps (0–10), boolean ("true"/"false" keys), and
ordinal (declare points and a mapping with exactly that many choices). A question
with no scoring block is unscored - the answer is still recorded verbatim. A scored
question requires an id (answers key on it) and question text.
The shape is contract-enforced: a malformed block - an unknown scale, mapping keys
outside the scale’s answer set, ordinal without a matching points - is a 422 at
write time and a 409 objective_scoring_invalid at publish, with errors[] naming
each broken field. It cannot silently publish and yield score: null.
Captured summary answers
Section titled “Captured summary answers”An objective can also declare capture_type as string, number, or boolean
for information extracted into post-call summaries. For example:
{ "id": "years_experience", "prompt": "How many years of driving experience do you have?", "capture_type": "number"}Typed captures require a unique id or legacy name and question text. In the
portal objective editor, choose Text, Number, or Yes or no under Captured answer
type. Unspecified preserves the existing behavior. This setting controls summary
extraction; it does not alter survey scoring or make an assignment or hiring decision.
Where automatic summaries are enabled, missing or refused answers remain absent; an explicit no or zero remains a captured answer. Replies with incorrect types are rejected and retried instead of silently converting strings into answers. Declaring a type does not enable automatic summaries for a deployment without a qualified model.
Per-call questions
Section titled “Per-call questions”POST /v1/calls accepts up to 10 additional questions and up to 20 context facts for
that one call:
{ "agent_id": "agnt_01J9…", "contact_id": "cont_01J9…", "questions": [ { "id": "q_delivered", "prompt": "Did yesterday's delivery arrive on time?", "scoring": { "scale": "boolean", "mapping": { "true": 1, "false": 0 } } } ], "context": { "order_number": "A-1009", "delivery_date": "yesterday" }}The rules:
- Additive only. A per-call question may not reuse an id the version’s objectives
already carry -
409 call_question_conflict. The published, evaluation-gated objectives are never overridden per call. - The version must grant
record_survey_answer. Otherwise the answers would have no tool to record them -409 call_questions_unsupportedat launch, not a silent no-op after the call. - Context keys are snake_case strings, ≤500 characters each, ≤8 KiB total.
Platform-authored keys (
current_datetime,contact_name, …) are refused - you cannot shadow what the platform tells the agent.
Per-call questions ride outside the agent’s cached prompt prefix, so they add no
latency penalty, and they score into the same SurveyResponse as version objectives.
Reading the answers
Section titled “Reading the answers”- Push:
survey.completedandcall.endedwebhooks carryanswersandscoreinline - see Receive results. - Pull:
GET /v1/survey-responses?call_id=…returns{answers: {id: {answer, verbatim_quote, confidence}}, score, completion_status}. - Aggregate:
GET /v1/campaigns/{id}/survey-rollupfor campaign questions.
The score is computed once, at call completion, from the exact question set the call ran - deterministic and reproducible; editing the agent later never restates a past response.