submit_answer
Deprecated name of answer_purchase_question; same input and result.
POST https://api.envoy.money/tools/submit_answer
Deprecated name of answer_purchase_question; same input and result. Prefer answer_purchase_question.
| Title | Service | Read only | Destructive | Idempotent | External sites |
|---|---|---|---|---|---|
| Answer Envoy (old name) | shared | false | false | true | false |
Send a Central Auth bearer with agent scope. A key-bound connection also sends Envoy-Installation-Proof over this exact request. JSON bodies are limited to 64 KB; a larger body returns HTTP 413 with INVALID_INPUT.
Input
| Field | Required | Type | Description and rules |
|---|---|---|---|
type | Yes | "details" | "answer" | "feedback" | What you are sending. details: a missing detail Envoy asked for. answer: the user's reply to purchase.question. feedback: the user's view, after purchase.follow_up or at any time. Envoy matches it to the open question. |
answer | Yes | string | What the user said, in their words: the reply to purchase.question, or feedback after purchase.follow_up. An otp question asks for the code the merchant sent the user to sign in: send it once, then never repeat or keep it. Never your own answer, and never a password, a payment or bank code, or a card detail. minLength 1; maxLength 800 |
purchase | No | string | Purchase ID or original idempotency key. minLength 16; maxLength 64; pattern ^(?:pur_[a-f0-9]{32}|(?:[A-Za-oq-z0-9_-]|p[A-Za-tv-z0-9_-]|pu[A-Za-qs-z0-9_-]|pur[A-Za-z0-9-])[A-Za-z0-9_-]*)$ |
question | No | string | The id from purchase.question or purchase.follow_up. An earlier question cannot be answered. minLength 1; maxLength 128 |
rating | No | integer | Rating from 1 to 5. Feedback only. minimum 1; maximum 5 |
idempotency_key | Yes | string | One key per answer. Retry with the same key and the same answer; a reused key with a different answer is refused. minLength 16; maxLength 64; pattern ^(?:[A-Za-oq-z0-9_-]|p[A-Za-tv-z0-9_-]|pu[A-Za-qs-z0-9_-]|pur[A-Za-z0-9-])[A-Za-z0-9_-]*$ |
Unknown fields are rejected. The exact input schema is on the schemas page.
Synthetic request
{
"type": "answer",
"purchase": "synthetic-intent-0001",
"question": "synthetic-question-0001",
"answer": "Buy the in-stock model instead.",
"idempotency_key": "synthetic-answer-0001"
}Success data
Every reply uses the shared envelope: ok, the purchase, next, user_action and error. Follow next; outputs may gain fields, so ignore ones you do not recognize.
This tool returns its payload in data:
Field in data | Required | Type | Description and rules |
|---|---|---|---|
receipt | Yes | object | Feedback receipt: present when answer_purchase_question recorded feedback. |
receipt.feedback_id | Yes | string | Feedback identifier. |
receipt.recorded_at | Yes | string | Recorded time. format date-time |
Synthetic result
Example synthetic-answer-relayed (synthetic data):
{
"ok": true,
"contract": "envoy@2026-10",
"tool": "submit_answer",
"request_id": "req_synthetic",
"trace_id": "4bf92f3577b34da6a3ce929d0e0e4736",
"server_time": "2026-09-29T12:00:00Z",
"replayed": false,
"purchase": {
"purchase_id": "pur_5b1e9c7a3f2d5a8e9c0b1d2e3f4a5b6c",
"service": "purchase",
"idempotency_key": "synthetic-intent-0001",
"revision": 2,
"terminal": false,
"state": "processing",
"user_task": null,
"reason_code": null,
"status_text": "Envoy is placing this order on the merchant site.",
"rail": "operated_checkout",
"rail_reason": "RAIL_AMOUNT_ABOVE_OTU_LIMIT",
"checkout_by": "envoy",
"merchant": {
"name": "Example Store",
"url": "https://shop.example.test"
},
"amount": {
"minor": 249900,
"currency": "INR",
"display": "₹2,499.00"
},
"description": "Headphones",
"details": {
"complete": true,
"missing": []
},
"question": null,
"follow_up": null,
"approval": {
"state": null,
"method": null,
"decide_by": null,
"approval_url": null
},
"payment_ready": {
"available": false,
"kind": null,
"expires_at": null
},
"money": {
"status": "not_started",
"paid": null,
"merchant_order_ref": null
},
"receipt": null,
"chain": {
"supersedes": null,
"superseded_by": null
},
"agent": {
"agent_id": "origin:https://host.example.test",
"display_name": "Synthetic Host",
"verification": "origin"
},
"created_at": "2026-09-29T12:00:00Z",
"updated_at": "2026-09-29T12:00:00Z"
},
"data": null,
"next": {
"action": "call_tool",
"tool": "get_purchase_status",
"args": {
"purchase": "pur_5b1e9c7a3f2d5a8e9c0b1d2e3f4a5b6c",
"after_revision": 2,
"wait_seconds": 45
},
"instruction": "Envoy is checking out for you. Do not open the merchant checkout or pay. Hold-read get_purchase_status until the state changes or next.by passes.",
"after_seconds": 0,
"by": "2026-09-29T12:02:00Z"
},
"user_action": null,
"follow_ups": [],
"error": null
}Errors
A failure has ok: false, changes nothing, and carries error plus one next. Branch on error.code and next, not on the HTTP status. The contract declares every code below for every tool; which one a call returns depends on the request and the purchase state.
| Code | HTTP status | Meaning | What the agent does |
|---|---|---|---|
INVALID_INPUT | 400 | Fix the supplied input. | Fix every field listed in error.fields, then call the same tool once more. |
UNAUTHENTICATED | 401 | Reconnect through Central Auth. | Ask the user to reconnect Envoy, then retry this call. |
NOT_ALLOWED | 403 | The operation is not allowed. | This connection may not do that. Tell the user; do not retry. |
SERVICE_NOT_ENABLED | 403 | The service is not enabled. | This Envoy service is not enabled for the user. Tell the user; do not retry. |
NOT_FOUND | 404 | Purchase absent or owned by another user. | No purchase matches that reference. Check the purchase id from this task; do not start a new purchase to recover. |
IDEMPOTENCY_CONFLICT | 409 | The same key has different input. | Retry with the original inputs unchanged, or use a new idempotency_key only for a genuinely new purchase. |
ACTIVE_PURCHASE_EXISTS | 409 | An active purchase already exists. | Another purchase is in progress. Show the user the user_action message and stop this attempt. |
STATE_CONFLICT | 409 | The operation conflicts with the current state. | This conflicts with the current state. Tell the user; do not retry. |
NO_RAIL | 422 | No rail can serve this purchase; nothing was created. | Envoy cannot pay this purchase. Tell the user why using error.message; do not retry or split it. |
RATE_LIMITED | 429 | Wait before retrying. | Wait next.after_seconds, then retry the same call unchanged. |
UNAVAILABLE | 503 | The service is unavailable; follow retryable and next. | Wait next.after_seconds, then retry the same call unchanged; never pay elsewhere meanwhile. |
CLIENT_UPDATE_REQUIRED | 426 | Update the client. | This client is too old. Tell the user to update it. |