answer_purchase_question

Use this when a purchase is waiting on the user (needs_details or needs_answer): send their reply to purchase.question, or feedback after purchase.follow_up, or at any time.

POST https://api.envoy.money/tools/answer_purchase_question

Use this when a purchase is waiting on the user (needs_details or needs_answer): send their reply to purchase.question, or feedback after purchase.follow_up, or at any time. Pass the question id and a type. Show the prompt verbatim and wait; never answer for the user. On kind otp it is the code the merchant sent the user to sign in: send it once, then never repeat or keep it. Never send a password, a payment or bank code, or a card detail. Supply a new idempotency_key for each new answer. Retry with the same key and answer. Then keep reading get_purchase_status.

TitleServiceRead onlyDestructiveIdempotentExternal sites
Answer a purchase questionsharedfalsefalsetruefalse

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

FieldRequiredTypeDescription and rules
typeYes"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.
answerYesstringWhat 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
purchaseNostringPurchase 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_-]*)$
questionNostringThe id from purchase.question or purchase.follow_up. An earlier question cannot be answered. minLength 1; maxLength 128
ratingNointegerRating from 1 to 5. Feedback only. minimum 1; maximum 5
idempotency_keyYesstringOne 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 dataRequiredTypeDescription and rules
receiptYesobjectFeedback receipt: present when answer_purchase_question recorded feedback.
receipt.feedback_idYesstringFeedback identifier.
receipt.recorded_atYesstringRecorded time. format date-time

Synthetic result

Example synthetic-answer-relayed (synthetic data):

{
  "ok": true,
  "contract": "envoy@2026-10",
  "tool": "answer_purchase_question",
  "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.

CodeHTTP statusMeaningWhat the agent does
INVALID_INPUT400Fix the supplied input.Fix every field listed in error.fields, then call the same tool once more.
UNAUTHENTICATED401Reconnect through Central Auth.Ask the user to reconnect Envoy, then retry this call.
NOT_ALLOWED403The operation is not allowed.This connection may not do that. Tell the user; do not retry.
SERVICE_NOT_ENABLED403The service is not enabled.This Envoy service is not enabled for the user. Tell the user; do not retry.
NOT_FOUND404Purchase 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_CONFLICT409The 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_EXISTS409An active purchase already exists.Another purchase is in progress. Show the user the user_action message and stop this attempt.
STATE_CONFLICT409The operation conflicts with the current state.This conflicts with the current state. Tell the user; do not retry.
NO_RAIL422No 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_LIMITED429Wait before retrying.Wait next.after_seconds, then retry the same call unchanged.
UNAVAILABLE503The service is unavailable; follow retryable and next.Wait next.after_seconds, then retry the same call unchanged; never pay elsewhere meanwhile.
CLIENT_UPDATE_REQUIRED426Update the client.This client is too old. Tell the user to update it.

Downloads

OpenAPI · MCP catalog · Synthetic examples · Schemas

On this page