{
"error": {
"code": "read_only_key",
"message": "This API key is read-only. Use a key without the read-only setting to create, change or cancel anything.",
"param": null,
"retryable": false,
"doc_url": "https://docs.listo.delivery/en/errors/read_only_key",
"request_id": "0b1f6c9a-7e2d-4c53-9a41-5d8e3f2a6b10"
}
}
{
"error": {
"code": "webhook_endpoint_not_configured",
"message": "There is no webhook URL configured for this mode, so there is nowhere to send it.",
"param": null,
"retryable": false,
"doc_url": "https://docs.listo.delivery/en/errors/webhook_endpoint_not_configured",
"request_id": "0b1f6c9a-7e2d-4c53-9a41-5d8e3f2a6b10"
}
}
{
"error": {
"code": "validation_failed",
"message": "That is not a webhook event type.",
"param": "type",
"retryable": false,
"doc_url": "https://docs.listo.delivery/en/errors/validation_failed",
"request_id": "0b1f6c9a-7e2d-4c53-9a41-5d8e3f2a6b10"
}
}
{
"error": {
"code": "test_webhook_limit_reached",
"message": "30 test webhooks were already sent in the last hour. Try again later.",
"param": null,
"retryable": true,
"doc_url": "https://docs.listo.delivery/en/errors/test_webhook_limit_reached",
"request_id": "0b1f6c9a-7e2d-4c53-9a41-5d8e3f2a6b10"
}
}
Events
Send a test webhook
Sends a synthetic event of one published type to your webhook URL, so
you can exercise an endpoint without placing an order. The answer is 202
with the event as your endpoint receives it, and the attempt appears on
GET /v1/webhook_deliveries like any other.
test: true is on the envelope. A real event never carries the
field. Branch on it before doing anything with consequences.
Its ids resolve to nothing.data is a realistic sample of the
type, but the delivery, store, withdrawal or quote it names does not
exist, so reading it back answers 404.
Either mode. A test key sends to your test endpoint and a live key
to your live one. The live endpoint does receive the test event.
Thirty an hour per mode. The thirty-first is
429 test_webhook_limit_reached, retryable once the hour has moved on.
Retry-After says how many seconds until you can send again.
A type that is not a published event type is 422 validation_failed
with param: "type". With no webhook URL configured for the key’s mode
the answer is 409 webhook_endpoint_not_configured.
{
"error": {
"code": "read_only_key",
"message": "This API key is read-only. Use a key without the read-only setting to create, change or cancel anything.",
"param": null,
"retryable": false,
"doc_url": "https://docs.listo.delivery/en/errors/read_only_key",
"request_id": "0b1f6c9a-7e2d-4c53-9a41-5d8e3f2a6b10"
}
}
{
"error": {
"code": "webhook_endpoint_not_configured",
"message": "There is no webhook URL configured for this mode, so there is nowhere to send it.",
"param": null,
"retryable": false,
"doc_url": "https://docs.listo.delivery/en/errors/webhook_endpoint_not_configured",
"request_id": "0b1f6c9a-7e2d-4c53-9a41-5d8e3f2a6b10"
}
}
{
"error": {
"code": "validation_failed",
"message": "That is not a webhook event type.",
"param": "type",
"retryable": false,
"doc_url": "https://docs.listo.delivery/en/errors/validation_failed",
"request_id": "0b1f6c9a-7e2d-4c53-9a41-5d8e3f2a6b10"
}
}
{
"error": {
"code": "test_webhook_limit_reached",
"message": "30 test webhooks were already sent in the last hour. Try again later.",
"param": null,
"retryable": true,
"doc_url": "https://docs.listo.delivery/en/errors/test_webhook_limit_reached",
"request_id": "0b1f6c9a-7e2d-4c53-9a41-5d8e3f2a6b10"
}
}
Your API key, sent as Authorization: Bearer <key>. Live and test keys are separate; the key you send decides which world the call acts in. To try calls, use a test key (it starts with lst_test_): no real courier is sent and no real money moves, but webhooks fire and the dropoff.phone you give can receive WhatsApp messages, so use your own number. A live key (it starts with lst_live_) books and charges real deliveries.
Accepted. The test event is the one your endpoint receives, test: true included (the test field of the event). The send is queued and happens right after this answer; its outcome is a new attempt on GET /v1/webhook_deliveries.
Option 1
Option 2
Option 3
Option 4
Option 5
Option 6
Every event your webhook endpoint receives, and every event the
debugging reads return: one of the six below, told apart by type.
data is the object the event is about, and its shape depends on
type. See WebhookEventEnvelope for the fields they all share and for
how delivery behaves (at-least-once, unordered).
The shape of a delivery: every field the object can carry, with the
nullability each one really has. It is the response of every operation
that answers a delivery (the create, the fetch, a list row, the
reschedule, the cancel, the retry and the refund) and the data of
every full delivery event, so ONE type holds all of them.
Every operation returns the whole object. A field that a given call
cannot yet have is present and null rather than missing: a create
response has a null courier, because no courier has been assigned
yet, and a reschedule only ever answers with a still-scheduled order,
so its delivered_at is null.
Money is integer centavos, timestamps are ISO-8601 in UTC, and every
enum below is ours rather than a passthrough of anyone else's.
Present, and true, only on a test event you asked for with
POST /v1/test_webhooks. A real event does not carry the field at
all. A test event's data is a sample whose ids resolve to nothing.
Example:
true
{"docsConfig":{"theme":"mint","$schema":"https://mintlify.com/docs.json","name":"Listo Partner API","description":"Quote, create and track deliveries, and manage your balance, through the Listo Partner Delivery API.","colors":{"primary":"#15171C","light":"#F4F4F5","dark":"#15171C"},"logo":{"light":"https://mintcdn.com/listo-c5a11a00/mreCwXzcEA2bSZog/logo/light.svg?fit=max\u0026auto=format\u0026n=mreCwXzcEA2bSZog\u0026q=85\u0026s=da2b28d464dc6987329dfd5971085dd7","dark":"https://mintcdn.com/listo-c5a11a00/mreCwXzcEA2bSZog/logo/dark.svg?fit=max\u0026auto=format\u0026n=mreCwXzcEA2bSZog\u0026q=85\u0026s=ad013a6a0d979eb46c1cea550ec6a460","href":"/"},"favicon":"https://mintcdn.com/listo-c5a11a00/mreCwXzcEA2bSZog/favicon.svg?fit=max\u0026auto=format\u0026n=mreCwXzcEA2bSZog\u0026q=85\u0026s=f790496dfe0c2ad9971d8de95e45be8d","api":{"playground":{"display":"interactive"}},"thumbnails":{"preset":"minimal","appearance":"dark","background":"https://mintcdn.com/listo-c5a11a00/lF-Gm03tnDMquh_z/images/og-background.jpg?fit=max\u0026auto=format\u0026n=lF-Gm03tnDMquh_z\u0026q=85\u0026s=d73469201c8ffe28afc598d23fde5d84","fonts":{"family":"Archivo ExtraBold","source":"fonts/archivo-800.ttf","format":"ttf"},"eyebrow":{"source":"none"}},"markdown":{"instructions":["Notes on the Listo Partner Delivery API:","- Every endpoint is under `https://api.listo.delivery/v1/` and authenticates with a bearer API key.","- This documentation site is at https://docs.listo.delivery. The full machine-readable reference is the OpenAPI document at https://api.listo.delivery/docs/openapi.yaml (served by the API host, not by this site).","- Any page of this site is also available as raw markdown by appending `.md` to its URL, for example https://docs.listo.delivery/en/guides/webhooks.md. The index of every page is https://docs.listo.delivery/llms.txt and all of them in one file is https://docs.listo.delivery/llms-full.txt.","- Every page is published in English under https://docs.listo.delivery/en/ and in Spanish under https://docs.listo.delivery/es/, with the same path after the language. The API reference is under https://docs.listo.delivery/api-reference/ in English and https://docs.listo.delivery/es/api-reference/ in Spanish.","- To debug an integration yourself: `GET /v1/request_logs` lists the calls your keys made with what you sent and what was answered, `GET /v1/events` lists the events Listo emitted, `GET /v1/webhook_deliveries` lists every attempt to deliver them, `POST /v1/events/{id}/resend` sends one event again and `POST /v1/test_webhooks` sends a sample event (`\"test\": true`). The page https://docs.listo.delivery/en/guides/debugging describes them. A resent event is a snapshot from when it happened; `GET /v1/deliveries` is still how you recover current state.","- Every error response has `error.doc_url`, a page that explains that error code and what to do, and `error.request_id`, the same value as the `X-Request-Id` response header. All the pages are listed at https://docs.listo.delivery/en/errors. Filter `GET /v1/request_logs` with `request_id` to read the logged call.","- A `409 account_exists` from `POST /v1/stores` means the restaurant already has its own Listo account: connect it instead of creating it, as the page https://docs.listo.delivery/en/guides/connect-existing-account describes.","- Every live store carries one Plan Listo, charged to the partner. The exception is a connected restaurant that had already paid its current month: it keeps paying its own plan until its next renewal, shown as `paid_by: \"store\"` with the handover date in `pending_paid_by_on`. A `402 plan_required` from a quote, a delivery create or a retry means the store's plan is not paid or has ended; the page https://docs.listo.delivery/en/guides/plan-and-billing describes the plan, the `plan` block on a store and how to end or restart it.","- An AI assistant (Claude Code, Cursor, Codex) can act through the same API key at `https://api.listo.delivery/mcp`, an MCP server over Streamable HTTP authenticated with `Authorization: Bearer \u003cAPI key>`. Every tool runs the matching `/v1/` endpoint, and each one that moves money first previews and then needs a confirmation token; the page https://docs.listo.delivery/en/guides/connect-ai-client lists the tools and describes the two steps."]},"styling":{"latex":true},"navigation":{"languages":[{"language":"en","default":true,"navbar":{"links":[{"href":"https://status.listo.delivery","label":"Status"}]},"href":"en/quickstart"},{"language":"es","navbar":{"links":[{"href":"https://status.listo.delivery","label":"Estado del servicio"}]},"href":"es/quickstart"}]}},"deployment":{"deploymentMetadataValue":{"subdomain":"listo-c5a11a00","hasAudioNarration":false,"actualSubdomain":"listo-c5a11a00","customDomains":["docs.listo.delivery"],"gitSource":{"type":"github","owner":"davidalejandroaguilar","repo":"listo","deployBranch":"main","contentDirectory":"docs-site","isPrivate":true,"mountPath":"","label":"","_id":"6aed6954347cccfbc77ed1c5"},"entitlements":{"AI_CHAT":{"status":"ENABLED"},"WEB_MCP":{"status":"ENABLED"},"NARRATION":{"status":"ENABLED"}},"buildId":"6aeeb167ae7fce64eae954de","clientVersion":"0.0.4076","searchFilterCounts":[{"language":"en","tag":"Errors","count":43},{"language":"en","tag":"Reference","count":43},{"language":"es","tag":"Errores","count":43},{"language":"es","tag":"Referencia","count":43},{"language":"en","tag":"Guides","count":9},{"language":"es","tag":"Guías","count":9},{"language":"en","tag":"Stores","count":8},{"language":"es","tag":"Tiendas","count":8},{"language":"en","tag":"Deliveries","count":7},{"language":"es","tag":"Envíos","count":7},{"language":"en","tag":"Webhooks","count":6},{"language":"es","tag":"Webhooks","count":6},{"language":"en","tag":"Concepts","count":5},{"language":"es","tag":"Conceptos","count":5},{"language":"en","tag":"Card onboarding","count":4},{"language":"en","tag":"Events","count":4},{"language":"es","tag":"Alta de cobros con tarjeta","count":4},{"language":"es","tag":"Eventos","count":4},{"language":"en","tag":"Withdrawals","count":3},{"language":"es","tag":"Retiros","count":3}]},"assistantConfig":{"enableAskAiButton":false,"enableStarterQuestions":false,"enableContextualStarterQuestions":false,"enableAskAiSearchBar":true},"basePath":"","hasChatPermissions":true,"hasWebMcpPermissions":true,"toggles":[{"name":"kill-isr","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"agent-mintlify-slack","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"agent-integrations-settings","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"rbac-expansion","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"automations-pr-grouping","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"custom-prefix","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"analytics-v7","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"user-flows-analytics","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"no-publish-flow","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"workos-onboarding","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"llms-txt-v2","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"snapshot-serving-live","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"stripTemperatureMiddleware","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"support-platform-pylon-zendesk","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"snapshot-serving","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"instant-rollback","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"granular-notifications-server","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"granular-notifications","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"automations-fable","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"fixed-ai-action-pricing","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"automation-resolve-merge-conflict","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"scoped-publishing","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"mintql","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"page-level-analytics","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"editor-version-history-v2","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"billing-page-v2","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"full-page-search","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"workspace-projects","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"assistant-v5","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"fork-pr-previews","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"revalidation-jwt","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"workos-sso-scim","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"hobby-abuse-scan","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"dashboard-inbox","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"workos-signup","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"turbopuffer-dual-write","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"workos-enabled","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"approve-review-flow","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"editor-metadata","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"sso-setup-deadline-banner","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"turbopuffer-serve","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"live-agents","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"comment-mode","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false}],"googleFontsInlined":false},"customCss":[{"filePath":"style.css","content":":is(#sidebar-content,#mobile-nav) li[data-active=\"true\"]>a{background-color:#ffc400;color:#15171c}"}],"page":{"pagePath":"api-reference/events/send-a-test-webhook","slug":"/api-reference/events/send-a-test-webhook","pageMetadata":{"title":"Send a test webhook","description":"Sends a synthetic event of one published `type` to your webhook URL, so\nyou can exercise an endpoint without placing an order. The answer is `202`\nwith the event as your endpoint receives it, and the attempt appears on\n`GET /v1/webhook_deliveries` like any other.\n\n- **`test: true` is on the envelope.** A real event never carries the\n field. Branch on it before doing anything with consequences.\n- **Its ids resolve to nothing.** `data` is a realistic sample of the\n type, but the delivery, store, withdrawal or quote it names does not\n exist, so reading it back answers `404`.\n- **Either mode.** A test key sends to your test endpoint and a live key\n to your live one. The live endpoint does receive the test event.\n- **Thirty an hour per mode.** The thirty-first is\n `429 test_webhook_limit_reached`, retryable once the hour has moved on.\n `Retry-After` says how many seconds until you can send again.\n\nA `type` that is not a published event type is `422 validation_failed`\nwith `param: \"type\"`. With no webhook URL configured for the key's mode\nthe answer is `409 webhook_endpoint_not_configured`.\n","deprecated":null,"version":null,"openapi":"/openapi/en.yaml post /v1/test_webhooks","href":"/api-reference/events/send-a-test-webhook","autogeneratedByOpenApi":true},"description":{"compiledSource":"\"use strict\";\nconst {Fragment: _Fragment, jsx: _jsx, jsxs: _jsxs} = arguments[0];\nconst {useMDXComponents: _provideComponents} = arguments[0];\nfunction _createMdxContent(props) {\n const _components = {\n code: \"code\",\n li: \"li\",\n p: \"p\",\n strong: \"strong\",\n ul: \"ul\",\n ..._provideComponents(),\n ...props.components\n };\n return _jsxs(_Fragment, {\n children: [_jsxs(_components.p, {\n children: [\"Sends a synthetic event of one published \", _jsx(_components.code, {\n children: \"type\"\n }), \" to your webhook URL, so\\nyou can exercise an endpoint without placing an order. The answer is \", _jsx(_components.code, {\n children: \"202\"\n }), \"\\nwith the event as your endpoint receives it, and the attempt appears on\\n\", _jsx(_components.code, {\n children: \"GET /v1/webhook_deliveries\"\n }), \" like any other.\"]\n }), \"\\n\", _jsxs(_components.ul, {\n children: [\"\\n\", _jsxs(_components.li, {\n children: [_jsxs(_components.strong, {\n children: [_jsx(_components.code, {\n children: \"test: true\"\n }), \" is on the envelope.\"]\n }), \" A real event never carries the\\nfield. Branch on it before doing anything with consequences.\"]\n }), \"\\n\", _jsxs(_components.li, {\n children: [_jsx(_components.strong, {\n children: \"Its ids resolve to nothing.\"\n }), \" \", _jsx(_components.code, {\n children: \"data\"\n }), \" is a realistic sample of the\\ntype, but the delivery, store, withdrawal or quote it names does not\\nexist, so reading it back answers \", _jsx(_components.code, {\n children: \"404\"\n }), \".\"]\n }), \"\\n\", _jsxs(_components.li, {\n children: [_jsx(_components.strong, {\n children: \"Either mode.\"\n }), \" A test key sends to your test endpoint and a live key\\nto your live one. The live endpoint does receive the test event.\"]\n }), \"\\n\", _jsxs(_components.li, {\n children: [_jsx(_components.strong, {\n children: \"Thirty an hour per mode.\"\n }), \" The thirty-first is\\n\", _jsx(_components.code, {\n children: \"429 test_webhook_limit_reached\"\n }), \", retryable once the hour has moved on.\\n\", _jsx(_components.code, {\n children: \"Retry-After\"\n }), \" says how many seconds until you can send again.\"]\n }), \"\\n\"]\n }), \"\\n\", _jsxs(_components.p, {\n children: [\"A \", _jsx(_components.code, {\n children: \"type\"\n }), \" that is not a published event type is \", _jsx(_components.code, {\n children: \"422 validation_failed\"\n }), \"\\nwith \", _jsx(_components.code, {\n children: \"param: \\\"type\\\"\"\n }), \". With no webhook URL configured for the key’s mode\\nthe answer is \", _jsx(_components.code, {\n children: \"409 webhook_endpoint_not_configured\"\n }), \".\"]\n })]\n });\n}\nfunction MDXContent(props = {}) {\n const {wrapper: MDXLayout} = {\n ..._provideComponents(),\n ...props.components\n };\n return MDXLayout ? _jsx(MDXLayout, {\n ...props,\n children: _jsx(_createMdxContent, {\n ...props\n })\n }) : _createMdxContent(props);\n}\nreturn {\n default: MDXContent\n};\n","frontmatter":{},"scope":{}},"pageType":"default","mdx":{"mdxSource":{"compiledSource":"\"use strict\";const{Fragment:_Fragment,jsx:_jsx}=arguments[0];const{useMDXComponents:_provideComponents}=arguments[0];function _createMdxContent(props){return _jsx(_Fragment,{})}function MDXContent(props={}){const{wrapper:MDXLayout}={..._provideComponents(),...props.components};return MDXLayout?_jsx(MDXLayout,{...props,children:_jsx(_createMdxContent,{...props})}):_createMdxContent(props)}return{default:MDXContent}","frontmatter":{},"scope":{"config":{},"pageMetadata":{"title":"Send a test webhook","description":"Sends a synthetic event of one published `type` to your webhook URL, so\nyou can exercise an endpoint without placing an order. The answer is `202`\nwith the event as your endpoint receives it, and the attempt appears on\n`GET /v1/webhook_deliveries` like any other.\n\n- **`test: true` is on the envelope.** A real event never carries the\n field. Branch on it before doing anything with consequences.\n- **Its ids resolve to nothing.** `data` is a realistic sample of the\n type, but the delivery, store, withdrawal or quote it names does not\n exist, so reading it back answers `404`.\n- **Either mode.** A test key sends to your test endpoint and a live key\n to your live one. The live endpoint does receive the test event.\n- **Thirty an hour per mode.** The thirty-first is\n `429 test_webhook_limit_reached`, retryable once the hour has moved on.\n `Retry-After` says how many seconds until you can send again.\n\nA `type` that is not a published event type is `422 validation_failed`\nwith `param: \"type\"`. With no webhook URL configured for the key's mode\nthe answer is `409 webhook_endpoint_not_configured`.\n","deprecated":null,"version":null,"openapi":"/openapi/en.yaml post /v1/test_webhooks","href":"/api-reference/events/send-a-test-webhook","autogeneratedByOpenApi":true}}},"mdxSourceWithNoJs":null},"mdxExtracts":{"tableOfContents":[],"codeExamples":{}},"jsLinks":[],"openApiReferenceData":{"operation":{"summary":"Send a test webhook","description":"Sends a synthetic event of one published `type` to your webhook URL, so\nyou can exercise an endpoint without placing an order. The answer is `202`\nwith the event as your endpoint receives it, and the attempt appears on\n`GET /v1/webhook_deliveries` like any other.\n\n- **`test: true` is on the envelope.** A real event never carries the\n field. Branch on it before doing anything with consequences.\n- **Its ids resolve to nothing.** `data` is a realistic sample of the\n type, but the delivery, store, withdrawal or quote it names does not\n exist, so reading it back answers `404`.\n- **Either mode.** A test key sends to your test endpoint and a live key\n to your live one. The live endpoint does receive the test event.\n- **Thirty an hour per mode.** The thirty-first is\n `429 test_webhook_limit_reached`, retryable once the hour has moved on.\n `Retry-After` says how many seconds until you can send again.\n\nA `type` that is not a published event type is `422 validation_failed`\nwith `param: \"type\"`. With no webhook URL configured for the key's mode\nthe answer is `409 webhook_endpoint_not_configured`.\n","tags":["Events"],"operationId":"sendTestWebhook","security":["cd7f4a15-648b-441e-9a2d-1d5b4d0b3653"],"requestBody":"4eb1abe6-f2e2-4236-b43a-6cb8771b2b9c","responses":{"202":"e0bfafa3-96c2-45b5-9dc9-abc8fd9b560a","403":"2b60cad3-caa1-48aa-8cc0-86def9166bfd","409":"5a50c2f5-34ae-47bd-bf8d-59473ad4b83d","422":"fa847c57-f1eb-41b2-9e78-e8d3955de6d2","429":"8ce481e4-bac6-4373-887e-fdec406ee13a"},"method":"post","type":"path","servers":["a658606d-cd78-44bb-b1d3-622847e198a1"],"path":"/v1/test_webhooks","baseUrlOptions":["https://api.listo.delivery"],"title":"Send a test webhook","codeSamples":[],"requiredOnlyExamples":false,"requestExampleType":"generated","responseExampleType":"generated"},"dependencies":{"parameters":{},"requestBody":{"content":{"application/json":{"schema":{"type":"object","description":"Which event to send a sample of.","properties":{"type":{"type":"string","enum":["delivery.status_changed","delivery.updated","delivery.courier_location","withdrawal.updated","store.updated","store.connected"],"description":"The published event type to send a sample of.","isRequired":true,"uniqueKey":"type","typeLabel":"enum\u003cstring>"}},"required":["type"],"uniqueKey":"","typeLabel":"object"},"example":{"type":"delivery.status_changed"},"examples":{"Example":{"title":"Example","value":{"type":"delivery.status_changed"}}},"exampleType":"examples"}},"required":true,"exampleType":"examples"},"responses":{"e0bfafa3-96c2-45b5-9dc9-abc8fd9b560a":{"description":"Accepted. The test event is the one your endpoint receives, `test: true` included (the `test` field of the event). The send is queued and happens right after this answer; its outcome is a new attempt on `GET /v1/webhook_deliveries`.","content":{"application/json":{"schema":{"oneOf":[{"type":"object","description":"Every event your webhook endpoint receives, and every event the\ndebugging reads return: one of the six below, told apart by `type`.\n`data` is the object the event is about, and its shape depends on\n`type`. See `WebhookEventEnvelope` for the fields they all share and for\nhow delivery behaves (at-least-once, unordered).\n","required":["type","data","id","created_at"],"properties":{"id":{"type":"string","description":"The event id, `evt_` prefixed. Dedupe on this.","example":"evt_9pQ2vX7mKdR4tYb1nZ3sLwCe","isRequired":true,"uniqueKey":"oneOf.0.id","typeLabel":"string"},"created_at":{"type":"string","format":"date-time","description":"When the event was recorded, ISO-8601 in UTC.","example":"2026-07-28T18:41:03Z","isRequired":true,"uniqueKey":"oneOf.0.created_at","typeLabel":"string\u003cdate-time>"},"type":{"type":"string","description":"Which event this is.","enum":["delivery.status_changed"],"isRequired":true,"uniqueKey":"oneOf.0.type","typeLabel":"enum\u003cstring>"},"data":{"type":"object","description":"The shape of a delivery: every field the object can carry, with the\nnullability each one really has. It is the response of every operation\nthat answers a delivery (the create, the fetch, a list row, the\nreschedule, the cancel, the retry and the refund) and the `data` of\nevery full delivery event, so ONE type holds all of them.\n\nEvery operation returns the whole object. A field that a given call\ncannot yet have is present and null rather than missing: a create\nresponse has a null `courier`, because no courier has been assigned\nyet, and a reschedule only ever answers with a still-scheduled order,\nso its `delivered_at` is null.\n\nMoney is integer centavos, timestamps are ISO-8601 in UTC, and every\nenum below is ours rather than a passthrough of anyone else's.\n","properties":{"id":{"type":"string","description":"The delivery id, `dlv_` prefixed.","example":"dlv_7hK2mQ9xR4tV6bN1cZ8sLwYe","isRequired":true,"uniqueKey":"oneOf.0.data.id","typeLabel":"string"},"external_id":{"oneOf":[{"type":"string","description":"Your own order reference, echoed back exactly as you sent it.","example":"order-841","isRequired":true,"uniqueKey":"oneOf.0.data.external_id.oneOf.0","typeLabel":"string"},{"type":"null","description":"Your own order reference, echoed back exactly as you sent it.","example":"order-841","isRequired":true,"uniqueKey":"oneOf.0.data.external_id.oneOf.1","typeLabel":"null"}],"isRequired":true,"uniqueKey":"oneOf.0.data.external_id","typeLabel":"string | null"},"origin":{"type":"string","enum":["api","console","whatsapp"],"description":"Which lane created the delivery. `api` is one you created through\n`POST /v1/deliveries`. `console` is one the store dispatched itself\nfrom the Listo merchant console, which a store can do only at the\n`full` access tier. `whatsapp` is one a customer ordered from the\nstore in a chat, which the store then accepted; no operator typed\nit anywhere.\n\nAlways present, never null, and fixed for the life of the delivery.\nA console order carries a null `external_id`, but read this field\nrather than that null: the missing reference is a consequence of the\nlane, not a way of identifying it.\n","example":"api","isRequired":true,"uniqueKey":"oneOf.0.data.origin","typeLabel":"enum\u003cstring>"},"code":{"type":"string","description":"The human order code the courier and our support quote. Unique per\nstore, not globally, so never address an order by it.\n","example":"LS-2048","isRequired":true,"uniqueKey":"oneOf.0.data.code","typeLabel":"string"},"status":{"type":"string","enum":["awaiting_payment","awaiting_location","scheduled","dispatching","courier_assigned","picking_up","en_route","returning","delivered","returned","canceled","no_courier"],"description":"`delivered`, `returned` and `canceled` are terminal. `no_courier` is\na dead end you can retry or cancel. A `returned` delivery is this\nsame object throughout; there is no second delivery for the return\nleg.\n\n`returning`: the drop-off failed and the courier is bringing the\norder back to the store; it ends in `returned`. It is NOT terminal,\nand it is where a failed delivery now spends the minutes between the\ncourier giving up at the customer's door and the order actually\narriving back. `returned` means the order is back. Treat `returning`\nas a live delivery: the courier is still moving and\n`delivery.courier_location` events keep arriving for it.\n\nThe return charge is posted when the delivery enters `returning`,\nnot when it reaches `returned`, so `charges` is already complete on\nthe `returning` event.\n\n`awaiting_location`: an order the store took through Listo's console\nor its WhatsApp assistant, held for the drop-off location. No\ncourier is requested yet. The customer confirms the location on a\nmap link or by sharing it in the WhatsApp chat, or the store\nconfirms it from its console. The delivery then moves to\n`scheduled` or `dispatching`; to `no_courier` when a courier\ncannot be requested for it (the location is outside where the\nstore delivers, or the store itself cannot request a courier right\nnow); or to `canceled` if the order is canceled or the store\nchanges it to a pickup at the counter. A delivery you create\nthrough this API never sits in it.\n","isRequired":true,"uniqueKey":"oneOf.0.data.status","typeLabel":"enum\u003cstring>"},"store_id":{"type":"string","description":"The `st_` id of the store the courier collects from.","isRequired":true,"uniqueKey":"oneOf.0.data.store_id","typeLabel":"string"},"test":{"type":"boolean","description":"Whether this order lives in the sandbox. Derived from the store, so\nthere is no field to set: a test key can only reach test stores.\n","isRequired":true,"uniqueKey":"oneOf.0.data.test","typeLabel":"boolean"},"payment":{"type":"object","description":"How the customer pays, and where that got to.","properties":{"method":{"type":"string","enum":["prepaid","cash","card"],"isRequired":true,"uniqueKey":"oneOf.0.data.payment.method","typeLabel":"enum\u003cstring>"},"status":{"type":"string","enum":["unpaid","awaiting_payment","paid","partially_refunded","refunded"],"isRequired":true,"uniqueKey":"oneOf.0.data.payment.status","typeLabel":"enum\u003cstring>"},"url":{"oneOf":[{"type":"string","format":"uri","description":"The branded payment link for a card order still awaiting\npayment. Listo sends it to your customer itself, by WhatsApp\nand by SMS when the WhatsApp does not reach them, so you can\nshow it or keep it but need not send it. Null the moment the\norder is paid or cancelled, because the link is then dead.\n","isRequired":true,"uniqueKey":"oneOf.0.data.payment.url.oneOf.0","typeLabel":"string\u003curi>"},{"type":"null","format":"uri","description":"The branded payment link for a card order still awaiting\npayment. Listo sends it to your customer itself, by WhatsApp\nand by SMS when the WhatsApp does not reach them, so you can\nshow it or keep it but need not send it. Null the moment the\norder is paid or cancelled, because the link is then dead.\n","isRequired":true,"uniqueKey":"oneOf.0.data.payment.url.oneOf.1","typeLabel":"null"}],"isRequired":true,"uniqueKey":"oneOf.0.data.payment.url","typeLabel":"string\u003curi> | null"},"cash_to_collect_cents":{"oneOf":[{"type":"integer","description":"What the courier collects at the door: the goods value plus the\ncustomer's share of the fee. Null, not zero, on any order that\nis not cash. Zero is a real value on a cash order whose door\ntotal is zero (a `0` order value you fully cover); such an order\nis dispatched with no collection to make.\n","isRequired":true,"uniqueKey":"oneOf.0.data.payment.cash_to_collect_cents.oneOf.0","typeLabel":"integer"},{"type":"null","description":"What the courier collects at the door: the goods value plus the\ncustomer's share of the fee. Null, not zero, on any order that\nis not cash. Zero is a real value on a cash order whose door\ntotal is zero (a `0` order value you fully cover); such an order\nis dispatched with no collection to make.\n","isRequired":true,"uniqueKey":"oneOf.0.data.payment.cash_to_collect_cents.oneOf.1","typeLabel":"null"}],"isRequired":true,"uniqueKey":"oneOf.0.data.payment.cash_to_collect_cents","typeLabel":"integer | null"},"paid_at":{"oneOf":[{"type":"string","format":"date-time","isRequired":true,"uniqueKey":"oneOf.0.data.payment.paid_at.oneOf.0","typeLabel":"string\u003cdate-time>"},{"type":"null","format":"date-time","isRequired":true,"uniqueKey":"oneOf.0.data.payment.paid_at.oneOf.1","typeLabel":"null"}],"isRequired":true,"uniqueKey":"oneOf.0.data.payment.paid_at","typeLabel":"string\u003cdate-time> | null"}},"required":["method","status","url","cash_to_collect_cents","paid_at"],"isRequired":true,"uniqueKey":"oneOf.0.data.payment","typeLabel":"object"},"order_value_cents":{"oneOf":[{"type":"integer","description":"The goods value you sent, untouched.","isRequired":true,"uniqueKey":"oneOf.0.data.order_value_cents.oneOf.0","typeLabel":"integer"},{"type":"null","description":"The goods value you sent, untouched.","isRequired":true,"uniqueKey":"oneOf.0.data.order_value_cents.oneOf.1","typeLabel":"null"}],"isRequired":true,"uniqueKey":"oneOf.0.data.order_value_cents","typeLabel":"integer | null"},"fee_cents":{"type":"integer","description":"The total delivery fee.","isRequired":true,"uniqueKey":"oneOf.0.data.fee_cents","typeLabel":"integer"},"business_fee_cents":{"type":"integer","description":"The part of `fee_cents` charged to you.","isRequired":true,"uniqueKey":"oneOf.0.data.business_fee_cents","typeLabel":"integer"},"customer_fee_cents":{"type":"integer","description":"The part of `fee_cents` charged to the customer. Always sums with\n`business_fee_cents` back to `fee_cents`.\n","isRequired":true,"uniqueKey":"oneOf.0.data.customer_fee_cents","typeLabel":"integer"},"tip_cents":{"type":"integer","description":"The courier tip you sent on this delivery, paid to the courier and\npassed on at cost with no margin taken. Deliberately OUTSIDE\n`fee_cents`, which is the delivery fee `business_fee_cents` and\n`customer_fee_cents` sum back to. 0 when you sent none, and never\nnull.\n","isRequired":true,"uniqueKey":"oneOf.0.data.tip_cents","typeLabel":"integer"},"currency":{"type":"string","enum":["MXN"],"isRequired":true,"uniqueKey":"oneOf.0.data.currency","typeLabel":"enum\u003cstring>"},"quote_id":{"oneOf":[{"type":"string","description":"The `qt_` quote this order bound, so you can tie the price you were\nquoted to the order that spent it. Null when the order was priced\ninline instead.\n","isRequired":true,"uniqueKey":"oneOf.0.data.quote_id.oneOf.0","typeLabel":"string"},{"type":"null","description":"The `qt_` quote this order bound, so you can tie the price you were\nquoted to the order that spent it. Null when the order was priced\ninline instead.\n","isRequired":true,"uniqueKey":"oneOf.0.data.quote_id.oneOf.1","typeLabel":"null"}],"isRequired":true,"uniqueKey":"oneOf.0.data.quote_id","typeLabel":"string | null"},"pickup":{"type":"object","description":"Where the courier collects, snapshotted at create, so a historical\norder keeps reporting where the courier actually went even after the\nstore is renamed or moved.\n","properties":{"name":{"type":"string","isRequired":true,"uniqueKey":"oneOf.0.data.pickup.name","typeLabel":"string"},"street":{"type":"string","isRequired":true,"uniqueKey":"oneOf.0.data.pickup.street","typeLabel":"string"},"lat":{"oneOf":[{"type":"number","format":"double","isRequired":true,"uniqueKey":"oneOf.0.data.pickup.lat.oneOf.0","typeLabel":"number\u003cdouble>"},{"type":"null","format":"double","isRequired":true,"uniqueKey":"oneOf.0.data.pickup.lat.oneOf.1","typeLabel":"null"}],"isRequired":true,"uniqueKey":"oneOf.0.data.pickup.lat","typeLabel":"number\u003cdouble> | null"},"lng":{"oneOf":[{"type":"number","format":"double","isRequired":true,"uniqueKey":"oneOf.0.data.pickup.lng.oneOf.0","typeLabel":"number\u003cdouble>"},{"type":"null","format":"double","isRequired":true,"uniqueKey":"oneOf.0.data.pickup.lng.oneOf.1","typeLabel":"null"}],"isRequired":true,"uniqueKey":"oneOf.0.data.pickup.lng","typeLabel":"number\u003cdouble> | null"},"notes":{"oneOf":[{"type":"string","description":"The store's standing pickup instructions, not a per-order value.","isRequired":true,"uniqueKey":"oneOf.0.data.pickup.notes.oneOf.0","typeLabel":"string"},{"type":"null","description":"The store's standing pickup instructions, not a per-order value.","isRequired":true,"uniqueKey":"oneOf.0.data.pickup.notes.oneOf.1","typeLabel":"null"}],"isRequired":true,"uniqueKey":"oneOf.0.data.pickup.notes","typeLabel":"string | null"}},"required":["name","street","lat","lng","notes"],"isRequired":true,"uniqueKey":"oneOf.0.data.pickup","typeLabel":"object"},"dropoff":{"type":"object","description":"Where the courier delivers, echoed back as you sent it.","properties":{"name":{"type":"string","isRequired":true,"uniqueKey":"oneOf.0.data.dropoff.name","typeLabel":"string"},"phone":{"type":"string","description":"E.164, normalized on the way in.","example":"+528112345678","isRequired":true,"uniqueKey":"oneOf.0.data.dropoff.phone","typeLabel":"string"},"street":{"type":"string","isRequired":true,"uniqueKey":"oneOf.0.data.dropoff.street","typeLabel":"string"},"apt_unit":{"oneOf":[{"type":"string","isRequired":true,"uniqueKey":"oneOf.0.data.dropoff.apt_unit.oneOf.0","typeLabel":"string"},{"type":"null","isRequired":true,"uniqueKey":"oneOf.0.data.dropoff.apt_unit.oneOf.1","typeLabel":"null"}],"isRequired":true,"uniqueKey":"oneOf.0.data.dropoff.apt_unit","typeLabel":"string | null"},"lat":{"oneOf":[{"type":"number","format":"double","description":"Null when the address was never geocoded and the text was judged\ninstead. Never a fabricated zero.\n","isRequired":true,"uniqueKey":"oneOf.0.data.dropoff.lat.oneOf.0","typeLabel":"number\u003cdouble>"},{"type":"null","format":"double","description":"Null when the address was never geocoded and the text was judged\ninstead. Never a fabricated zero.\n","isRequired":true,"uniqueKey":"oneOf.0.data.dropoff.lat.oneOf.1","typeLabel":"null"}],"isRequired":true,"uniqueKey":"oneOf.0.data.dropoff.lat","typeLabel":"number\u003cdouble> | null"},"lng":{"oneOf":[{"type":"number","format":"double","isRequired":true,"uniqueKey":"oneOf.0.data.dropoff.lng.oneOf.0","typeLabel":"number\u003cdouble>"},{"type":"null","format":"double","isRequired":true,"uniqueKey":"oneOf.0.data.dropoff.lng.oneOf.1","typeLabel":"null"}],"isRequired":true,"uniqueKey":"oneOf.0.data.dropoff.lng","typeLabel":"number\u003cdouble> | null"},"notes":{"oneOf":[{"type":"string","isRequired":true,"uniqueKey":"oneOf.0.data.dropoff.notes.oneOf.0","typeLabel":"string"},{"type":"null","isRequired":true,"uniqueKey":"oneOf.0.data.dropoff.notes.oneOf.1","typeLabel":"null"}],"isRequired":true,"uniqueKey":"oneOf.0.data.dropoff.notes","typeLabel":"string | null"},"handoff":{"type":"string","enum":["meet_at_door","leave_at_door","meet_outside"],"isRequired":true,"uniqueKey":"oneOf.0.data.dropoff.handoff","typeLabel":"enum\u003cstring>"}},"required":["name","phone","street","apt_unit","lat","lng","notes","handoff"],"isRequired":true,"uniqueKey":"oneOf.0.data.dropoff","typeLabel":"object"},"manifest":{"oneOf":[{"type":"object","description":"The descriptive item list you sent, for the courier. Money never\ncomes from it, with one exception: an item sized `xlarge` makes the\ntrip a car. Null when you sent none.\n","properties":{"items":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string","isRequired":true,"uniqueKey":"oneOf.0.data.manifest.oneOf.0.\\items.items.[INDEX].name","typeLabel":"string"},"quantity":{"type":"integer","isRequired":true,"uniqueKey":"oneOf.0.data.manifest.oneOf.0.\\items.items.[INDEX].quantity","typeLabel":"integer"},"size":{"type":"string","enum":["small","medium","large","xlarge"],"description":"What the item was sent as. `small` when you sent none,\nand on every item created before sizes existed, which is\nwhat those items were sent as.\n","isRequired":true,"uniqueKey":"oneOf.0.data.manifest.oneOf.0.\\items.items.[INDEX].size","typeLabel":"enum\u003cstring>"}},"required":["name","quantity","size"],"uniqueKey":"oneOf.0.data.manifest.oneOf.0.\\items.items.[INDEX]","typeLabel":"object"},"isRequired":true,"uniqueKey":"oneOf.0.data.manifest.oneOf.0.\\items","typeLabel":"object[]"}},"required":["items"],"isRequired":true,"uniqueKey":"oneOf.0.data.manifest.oneOf.0","typeLabel":"object"},{"type":"null","description":"The descriptive item list you sent, for the courier. Money never\ncomes from it, with one exception: an item sized `xlarge` makes the\ntrip a car. Null when you sent none.\n","properties":{"items":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string"},"quantity":{"type":"integer"},"size":{"type":"string","enum":["small","medium","large","xlarge"],"description":"What the item was sent as. `small` when you sent none,\nand on every item created before sizes existed, which is\nwhat those items were sent as.\n"}},"required":["name","quantity","size"]}}},"required":["items"],"isRequired":true,"uniqueKey":"oneOf.0.data.manifest.oneOf.1","typeLabel":"null"}],"isRequired":true,"uniqueKey":"oneOf.0.data.manifest","typeLabel":"object | null"},"vehicle":{"type":"string","enum":["moto","car"],"description":"What the trip was priced and dispatched as: `car` when you asked for\none or when an item was sized `xlarge`, `moto` otherwise. A car's\nsurcharge is inside `fee_cents`. Always present, never null, and\nfixed for the life of the delivery.\n\nNot the vehicle that arrived. That is `courier.vehicle_type`, which\ncan be a car on a `moto` trip without the fee changing.\n","example":"moto","isRequired":true,"uniqueKey":"oneOf.0.data.vehicle","typeLabel":"enum\u003cstring>"},"courier":{"oneOf":[{"type":"object","description":"Null until a courier is assigned, and then FROZEN: a terminal\ndelivery keeps reporting who carried it.\n","properties":{"name":{"type":"string","isRequired":true,"uniqueKey":"oneOf.0.data.courier.oneOf.0.name","typeLabel":"string"},"vehicle":{"oneOf":[{"type":"string","description":"What the courier is riding, in English whatever locale the\nrequest carried (\"Motorcycle\", \"Bicycle\"). Derived from\n`vehicle_type`, so it is null exactly when that is: display it,\nand switch on `vehicle_type` instead.\n","isRequired":true,"uniqueKey":"oneOf.0.data.courier.oneOf.0.vehicle.oneOf.0","typeLabel":"string"},{"type":"null","description":"What the courier is riding, in English whatever locale the\nrequest carried (\"Motorcycle\", \"Bicycle\"). Derived from\n`vehicle_type`, so it is null exactly when that is: display it,\nand switch on `vehicle_type` instead.\n","isRequired":true,"uniqueKey":"oneOf.0.data.courier.oneOf.0.vehicle.oneOf.1","typeLabel":"null"}],"isRequired":true,"uniqueKey":"oneOf.0.data.courier.oneOf.0.vehicle","typeLabel":"string | null"},"vehicle_type":{"oneOf":[{"type":"string","description":"The machine-readable type: `bicycle`, `car`, `van`, `truck`,\n`scooter`, `motorcycle` or `walker`. Null until the courier is\nassigned a vehicle. Treat an unlisted value as unknown rather\nthan an error: this list grows.\n","isRequired":true,"uniqueKey":"oneOf.0.data.courier.oneOf.0.vehicle_type.oneOf.0","typeLabel":"string"},{"type":"null","description":"The machine-readable type: `bicycle`, `car`, `van`, `truck`,\n`scooter`, `motorcycle` or `walker`. Null until the courier is\nassigned a vehicle. Treat an unlisted value as unknown rather\nthan an error: this list grows.\n","isRequired":true,"uniqueKey":"oneOf.0.data.courier.oneOf.0.vehicle_type.oneOf.1","typeLabel":"null"}],"isRequired":true,"uniqueKey":"oneOf.0.data.courier.oneOf.0.vehicle_type","typeLabel":"string | null"},"plate":{"oneOf":[{"type":"string","isRequired":true,"uniqueKey":"oneOf.0.data.courier.oneOf.0.plate.oneOf.0","typeLabel":"string"},{"type":"null","isRequired":true,"uniqueKey":"oneOf.0.data.courier.oneOf.0.plate.oneOf.1","typeLabel":"null"}],"isRequired":true,"uniqueKey":"oneOf.0.data.courier.oneOf.0.plate","typeLabel":"string | null"},"phone":{"oneOf":[{"type":"object","description":"A masked number and its IVR PIN, never a personal number. Dial\n`masked` and enter `pin` when the system asks. Null when no\nnumber has been issued for this courier.\n","properties":{"masked":{"type":"string","isRequired":true,"uniqueKey":"oneOf.0.data.courier.oneOf.0.phone.oneOf.0.masked","typeLabel":"string"},"pin":{"oneOf":[{"type":"string","isRequired":true,"uniqueKey":"oneOf.0.data.courier.oneOf.0.phone.oneOf.0.pin.oneOf.0","typeLabel":"string"},{"type":"null","isRequired":true,"uniqueKey":"oneOf.0.data.courier.oneOf.0.phone.oneOf.0.pin.oneOf.1","typeLabel":"null"}],"isRequired":true,"uniqueKey":"oneOf.0.data.courier.oneOf.0.phone.oneOf.0.pin","typeLabel":"string | null"}},"required":["masked","pin"],"isRequired":true,"uniqueKey":"oneOf.0.data.courier.oneOf.0.phone.oneOf.0","typeLabel":"object"},{"type":"null","description":"A masked number and its IVR PIN, never a personal number. Dial\n`masked` and enter `pin` when the system asks. Null when no\nnumber has been issued for this courier.\n","properties":{"masked":{"type":"string"},"pin":{"oneOf":[{"type":"string"},{"type":"null"}]}},"required":["masked","pin"],"isRequired":true,"uniqueKey":"oneOf.0.data.courier.oneOf.0.phone.oneOf.1","typeLabel":"null"}],"isRequired":true,"uniqueKey":"oneOf.0.data.courier.oneOf.0.phone","typeLabel":"object | null"},"location":{"oneOf":[{"type":"object","description":"The live position, present only while the courier is actually in\nmotion and only once there is a real fix.\n","properties":{"lat":{"type":"number","format":"double","isRequired":true,"uniqueKey":"oneOf.0.data.courier.oneOf.0.location.oneOf.0.lat","typeLabel":"number\u003cdouble>"},"lng":{"type":"number","format":"double","isRequired":true,"uniqueKey":"oneOf.0.data.courier.oneOf.0.location.oneOf.0.lng","typeLabel":"number\u003cdouble>"},"updated_at":{"oneOf":[{"type":"string","format":"date-time","isRequired":true,"uniqueKey":"oneOf.0.data.courier.oneOf.0.location.oneOf.0.updated_at.oneOf.0","typeLabel":"string\u003cdate-time>"},{"type":"null","format":"date-time","isRequired":true,"uniqueKey":"oneOf.0.data.courier.oneOf.0.location.oneOf.0.updated_at.oneOf.1","typeLabel":"null"}],"isRequired":true,"uniqueKey":"oneOf.0.data.courier.oneOf.0.location.oneOf.0.updated_at","typeLabel":"string\u003cdate-time> | null"}},"required":["lat","lng","updated_at"],"isRequired":true,"uniqueKey":"oneOf.0.data.courier.oneOf.0.location.oneOf.0","typeLabel":"object"},{"type":"null","description":"The live position, present only while the courier is actually in\nmotion and only once there is a real fix.\n","properties":{"lat":{"type":"number","format":"double"},"lng":{"type":"number","format":"double"},"updated_at":{"oneOf":[{"type":"string","format":"date-time"},{"type":"null","format":"date-time"}]}},"required":["lat","lng","updated_at"],"isRequired":true,"uniqueKey":"oneOf.0.data.courier.oneOf.0.location.oneOf.1","typeLabel":"null"}],"isRequired":true,"uniqueKey":"oneOf.0.data.courier.oneOf.0.location","typeLabel":"object | null"},"imminent":{"type":"boolean","description":"The courier is about a minute away. Always false once the trip ends.","isRequired":true,"uniqueKey":"oneOf.0.data.courier.oneOf.0.imminent","typeLabel":"boolean"}},"required":["name","vehicle","vehicle_type","plate","phone","location","imminent"],"isRequired":true,"uniqueKey":"oneOf.0.data.courier.oneOf.0","typeLabel":"object"},{"type":"null","description":"Null until a courier is assigned, and then FROZEN: a terminal\ndelivery keeps reporting who carried it.\n","properties":{"name":{"type":"string"},"vehicle":{"oneOf":[{"type":"string","description":"What the courier is riding, in English whatever locale the\nrequest carried (\"Motorcycle\", \"Bicycle\"). Derived from\n`vehicle_type`, so it is null exactly when that is: display it,\nand switch on `vehicle_type` instead.\n"},{"type":"null","description":"What the courier is riding, in English whatever locale the\nrequest carried (\"Motorcycle\", \"Bicycle\"). Derived from\n`vehicle_type`, so it is null exactly when that is: display it,\nand switch on `vehicle_type` instead.\n"}]},"vehicle_type":{"oneOf":[{"type":"string","description":"The machine-readable type: `bicycle`, `car`, `van`, `truck`,\n`scooter`, `motorcycle` or `walker`. Null until the courier is\nassigned a vehicle. Treat an unlisted value as unknown rather\nthan an error: this list grows.\n"},{"type":"null","description":"The machine-readable type: `bicycle`, `car`, `van`, `truck`,\n`scooter`, `motorcycle` or `walker`. Null until the courier is\nassigned a vehicle. Treat an unlisted value as unknown rather\nthan an error: this list grows.\n"}]},"plate":{"oneOf":[{"type":"string"},{"type":"null"}]},"phone":{"oneOf":[{"type":"object","description":"A masked number and its IVR PIN, never a personal number. Dial\n`masked` and enter `pin` when the system asks. Null when no\nnumber has been issued for this courier.\n","properties":{"masked":{"type":"string"},"pin":{"oneOf":[{"type":"string"},{"type":"null"}]}},"required":["masked","pin"]},{"type":"null","description":"A masked number and its IVR PIN, never a personal number. Dial\n`masked` and enter `pin` when the system asks. Null when no\nnumber has been issued for this courier.\n","properties":{"masked":{"type":"string"},"pin":{"oneOf":[{"type":"string"},{"type":"null"}]}},"required":["masked","pin"]}]},"location":{"oneOf":[{"type":"object","description":"The live position, present only while the courier is actually in\nmotion and only once there is a real fix.\n","properties":{"lat":{"type":"number","format":"double"},"lng":{"type":"number","format":"double"},"updated_at":{"oneOf":[{"type":"string","format":"date-time"},{"type":"null","format":"date-time"}]}},"required":["lat","lng","updated_at"]},{"type":"null","description":"The live position, present only while the courier is actually in\nmotion and only once there is a real fix.\n","properties":{"lat":{"type":"number","format":"double"},"lng":{"type":"number","format":"double"},"updated_at":{"oneOf":[{"type":"string","format":"date-time"},{"type":"null","format":"date-time"}]}},"required":["lat","lng","updated_at"]}]},"imminent":{"type":"boolean","description":"The courier is about a minute away. Always false once the trip ends."}},"required":["name","vehicle","vehicle_type","plate","phone","location","imminent"],"isRequired":true,"uniqueKey":"oneOf.0.data.courier.oneOf.1","typeLabel":"null"}],"isRequired":true,"uniqueKey":"oneOf.0.data.courier","typeLabel":"object | null"},"pickup_eta_at":{"oneOf":[{"type":"string","format":"date-time","description":"When the courier is expected at the store. Absolute, so you compute\nyour own countdown; a countdown computed here is stale before you\nread it.\n","isRequired":true,"uniqueKey":"oneOf.0.data.pickup_eta_at.oneOf.0","typeLabel":"string\u003cdate-time>"},{"type":"null","format":"date-time","description":"When the courier is expected at the store. Absolute, so you compute\nyour own countdown; a countdown computed here is stale before you\nread it.\n","isRequired":true,"uniqueKey":"oneOf.0.data.pickup_eta_at.oneOf.1","typeLabel":"null"}],"isRequired":true,"uniqueKey":"oneOf.0.data.pickup_eta_at","typeLabel":"string\u003cdate-time> | null"},"dropoff_eta_at":{"oneOf":[{"type":"string","format":"date-time","description":"When the courier is expected at the customer. Null until there is\nan estimate, and null again once the drop-off has failed\n(`returning`, `returned`): the courier is then bringing the order\nback to the store, there is no arrival at the customer left to\ndescribe, and the time it gets back to the store is never published\nhere.\n","isRequired":true,"uniqueKey":"oneOf.0.data.dropoff_eta_at.oneOf.0","typeLabel":"string\u003cdate-time>"},{"type":"null","format":"date-time","description":"When the courier is expected at the customer. Null until there is\nan estimate, and null again once the drop-off has failed\n(`returning`, `returned`): the courier is then bringing the order\nback to the store, there is no arrival at the customer left to\ndescribe, and the time it gets back to the store is never published\nhere.\n","isRequired":true,"uniqueKey":"oneOf.0.data.dropoff_eta_at.oneOf.1","typeLabel":"null"}],"isRequired":true,"uniqueKey":"oneOf.0.data.dropoff_eta_at","typeLabel":"string\u003cdate-time> | null"},"tracking_url":{"oneOf":[{"type":"string","format":"uri","description":"The branded live tracking page for the customer: the map, the\ncourier, the delivery code and what is owed at the door. Null when\nthere is no page to point at, so you never relay a dead link.\n\nThere is a page from the moment the order is dispatched, including\nthe whole window before a courier is assigned, and for 48 hours\nafter the order is delivered, canceled or returned. It is null while\nan order is still held awaiting payment or awaiting a confirmed\ndrop-off pin, and null again once that 48 hours has passed.\n","example":"https://app.listo.delivery/t/abc123","isRequired":true,"uniqueKey":"oneOf.0.data.tracking_url.oneOf.0","typeLabel":"string\u003curi>"},{"type":"null","format":"uri","description":"The branded live tracking page for the customer: the map, the\ncourier, the delivery code and what is owed at the door. Null when\nthere is no page to point at, so you never relay a dead link.\n\nThere is a page from the moment the order is dispatched, including\nthe whole window before a courier is assigned, and for 48 hours\nafter the order is delivered, canceled or returned. It is null while\nan order is still held awaiting payment or awaiting a confirmed\ndrop-off pin, and null again once that 48 hours has passed.\n","example":"https://app.listo.delivery/t/abc123","isRequired":true,"uniqueKey":"oneOf.0.data.tracking_url.oneOf.1","typeLabel":"null"}],"isRequired":true,"uniqueKey":"oneOf.0.data.tracking_url","typeLabel":"string\u003curi> | null"},"verification":{"oneOf":[{"type":"object","description":"Present only when the order carries a dropoff PIN: when you asked\nfor one (`verification.dropoff_pincode` on the create), or when\nListo requires a PIN on every delivery of this store's account, in\nwhich case it is present even though you did not ask. `pincode` is\nnull until the order is actually dispatched, which is when the code\nis minted.\n","properties":{"pincode":{"oneOf":[{"type":"string","isRequired":true,"uniqueKey":"oneOf.0.data.verification.oneOf.0.pincode.oneOf.0","typeLabel":"string"},{"type":"null","isRequired":true,"uniqueKey":"oneOf.0.data.verification.oneOf.0.pincode.oneOf.1","typeLabel":"null"}],"isRequired":true,"uniqueKey":"oneOf.0.data.verification.oneOf.0.pincode","typeLabel":"string | null"}},"required":["pincode"],"isRequired":true,"uniqueKey":"oneOf.0.data.verification.oneOf.0","typeLabel":"object"},{"type":"null","description":"Present only when the order carries a dropoff PIN: when you asked\nfor one (`verification.dropoff_pincode` on the create), or when\nListo requires a PIN on every delivery of this store's account, in\nwhich case it is present even though you did not ask. `pincode` is\nnull until the order is actually dispatched, which is when the code\nis minted.\n","properties":{"pincode":{"oneOf":[{"type":"string"},{"type":"null"}]}},"required":["pincode"],"isRequired":true,"uniqueKey":"oneOf.0.data.verification.oneOf.1","typeLabel":"null"}],"isRequired":true,"uniqueKey":"oneOf.0.data.verification","typeLabel":"object | null"},"return_verification":{"type":"object","description":"The return code (código de devolución). When an order cannot be\ndelivered and the courier brings it back to the store, the courier\nmust be given this code at the store to hand the order over; without\nit the return cannot be completed. `pincode` is a 4-digit string\nwhile the delivery is `returning`, and null in every other state\n(before the return, and once it is `returned`). The object is\nalways present, so this field never needs a presence check. It\narrives in `delivery.status_changed` (the move into `returning`) and\nin `delivery.updated`, which carry the whole object. A new attempt\n(a retry) gets its own code. Show it to the store, and never to the\ncustomer.\n","properties":{"pincode":{"oneOf":[{"type":"string","example":"4821","isRequired":true,"uniqueKey":"oneOf.0.data.return_verification.pincode.oneOf.0","typeLabel":"string"},{"type":"null","example":"4821","isRequired":true,"uniqueKey":"oneOf.0.data.return_verification.pincode.oneOf.1","typeLabel":"null"}],"isRequired":true,"uniqueKey":"oneOf.0.data.return_verification.pincode","typeLabel":"string | null"}},"required":["pincode"],"isRequired":true,"uniqueKey":"oneOf.0.data.return_verification","typeLabel":"object"},"proof":{"oneOf":[{"type":"object","description":"Proof of delivery. Null unless we hold some, and each field is null\nwhen that piece is missing; a photo with no signature is normal. The\nURLs are Listo's own signed links to the stored copy and are valid\nfor 24 hours from the response (or webhook) that carried them:\nfetch `GET /v1/deliveries/{id}` again for a fresh link, or keep a\ncopy. **A URL is null until Listo has its own copy of the image**\n(a few seconds after the courier takes it); the copy's arrival is\nannounced by a `delivery.updated` webhook that carries the link.\nIt may come from a delivery attempt that failed at the\ndoor, so it is not by itself proof that the order was handed over:\n`proofs.dropoff.delivered` says which. Prefer `proofs`, which keeps\neach moment of the trip apart.\n","properties":{"picture_url":{"oneOf":[{"type":"string","format":"uri","isRequired":true,"uniqueKey":"oneOf.0.data.proof.oneOf.0.picture_url.oneOf.0","typeLabel":"string\u003curi>"},{"type":"null","format":"uri","isRequired":true,"uniqueKey":"oneOf.0.data.proof.oneOf.0.picture_url.oneOf.1","typeLabel":"null"}],"isRequired":true,"uniqueKey":"oneOf.0.data.proof.oneOf.0.picture_url","typeLabel":"string\u003curi> | null"},"signature_image_url":{"oneOf":[{"type":"string","format":"uri","isRequired":true,"uniqueKey":"oneOf.0.data.proof.oneOf.0.signature_image_url.oneOf.0","typeLabel":"string\u003curi>"},{"type":"null","format":"uri","isRequired":true,"uniqueKey":"oneOf.0.data.proof.oneOf.0.signature_image_url.oneOf.1","typeLabel":"null"}],"isRequired":true,"uniqueKey":"oneOf.0.data.proof.oneOf.0.signature_image_url","typeLabel":"string\u003curi> | null"},"signature_name":{"oneOf":[{"type":"string","isRequired":true,"uniqueKey":"oneOf.0.data.proof.oneOf.0.signature_name.oneOf.0","typeLabel":"string"},{"type":"null","isRequired":true,"uniqueKey":"oneOf.0.data.proof.oneOf.0.signature_name.oneOf.1","typeLabel":"null"}],"isRequired":true,"uniqueKey":"oneOf.0.data.proof.oneOf.0.signature_name","typeLabel":"string | null"},"captured_at":{"oneOf":[{"type":"string","format":"date-time","isRequired":true,"uniqueKey":"oneOf.0.data.proof.oneOf.0.captured_at.oneOf.0","typeLabel":"string\u003cdate-time>"},{"type":"null","format":"date-time","isRequired":true,"uniqueKey":"oneOf.0.data.proof.oneOf.0.captured_at.oneOf.1","typeLabel":"null"}],"isRequired":true,"uniqueKey":"oneOf.0.data.proof.oneOf.0.captured_at","typeLabel":"string\u003cdate-time> | null"}},"required":["picture_url","signature_image_url","signature_name","captured_at"],"isRequired":true,"uniqueKey":"oneOf.0.data.proof.oneOf.0","typeLabel":"object"},{"type":"null","description":"Proof of delivery. Null unless we hold some, and each field is null\nwhen that piece is missing; a photo with no signature is normal. The\nURLs are Listo's own signed links to the stored copy and are valid\nfor 24 hours from the response (or webhook) that carried them:\nfetch `GET /v1/deliveries/{id}` again for a fresh link, or keep a\ncopy. **A URL is null until Listo has its own copy of the image**\n(a few seconds after the courier takes it); the copy's arrival is\nannounced by a `delivery.updated` webhook that carries the link.\nIt may come from a delivery attempt that failed at the\ndoor, so it is not by itself proof that the order was handed over:\n`proofs.dropoff.delivered` says which. Prefer `proofs`, which keeps\neach moment of the trip apart.\n","properties":{"picture_url":{"oneOf":[{"type":"string","format":"uri"},{"type":"null","format":"uri"}]},"signature_image_url":{"oneOf":[{"type":"string","format":"uri"},{"type":"null","format":"uri"}]},"signature_name":{"oneOf":[{"type":"string"},{"type":"null"}]},"captured_at":{"oneOf":[{"type":"string","format":"date-time"},{"type":"null","format":"date-time"}]}},"required":["picture_url","signature_image_url","signature_name","captured_at"],"isRequired":true,"uniqueKey":"oneOf.0.data.proof.oneOf.1","typeLabel":"null"}],"isRequired":true,"uniqueKey":"oneOf.0.data.proof","typeLabel":"object | null"},"proofs":{"type":"object","description":"The evidence the trip left, one entry per moment. Each moment is\nnull until it happens (nothing has been captured for it yet), so\nthis object is always present with its three keys. A photo or\nsignature link is Listo's own signed link to the stored copy, and\n**it is null until Listo holds that copy** (a few seconds after the\ncourier takes the photo): the rest of the moment, the signer, the\ntime and the distance, is there from the start, and when the copy\nlands a `delivery.updated` webhook carries the link. **Each link is\nvalid for 24 hours** from the response (or webhook) that carried\nit: it is a short-lived signed link, never a permanent one. A\npartner that needs the image later fetches\n`GET /v1/deliveries/{id}` again for a fresh link, or keeps a copy.\n","properties":{"pickup":{"oneOf":[{"type":"object","description":"The courier collecting the order at the store. Null until the\npickup photo exists.\n","properties":{"photo_url":{"oneOf":[{"type":"string","format":"uri","description":"Photo of the order at the store.","isRequired":true,"uniqueKey":"oneOf.0.data.proofs.pickup.oneOf.0.photo_url.oneOf.0","typeLabel":"string\u003curi>"},{"type":"null","format":"uri","description":"Photo of the order at the store.","isRequired":true,"uniqueKey":"oneOf.0.data.proofs.pickup.oneOf.0.photo_url.oneOf.1","typeLabel":"null"}],"isRequired":true,"uniqueKey":"oneOf.0.data.proofs.pickup.oneOf.0.photo_url","typeLabel":"string\u003curi> | null"},"captured_at":{"oneOf":[{"type":"string","format":"date-time","description":"When Listo first saw this photo.","isRequired":true,"uniqueKey":"oneOf.0.data.proofs.pickup.oneOf.0.captured_at.oneOf.0","typeLabel":"string\u003cdate-time>"},{"type":"null","format":"date-time","description":"When Listo first saw this photo.","isRequired":true,"uniqueKey":"oneOf.0.data.proofs.pickup.oneOf.0.captured_at.oneOf.1","typeLabel":"null"}],"isRequired":true,"uniqueKey":"oneOf.0.data.proofs.pickup.oneOf.0.captured_at","typeLabel":"string\u003cdate-time> | null"}},"required":["photo_url","captured_at"],"isRequired":true,"uniqueKey":"oneOf.0.data.proofs.pickup.oneOf.0","typeLabel":"object"},{"type":"null","description":"The courier collecting the order at the store. Null until the\npickup photo exists.\n","properties":{"photo_url":{"oneOf":[{"type":"string","format":"uri","description":"Photo of the order at the store."},{"type":"null","format":"uri","description":"Photo of the order at the store."}]},"captured_at":{"oneOf":[{"type":"string","format":"date-time","description":"When Listo first saw this photo."},{"type":"null","format":"date-time","description":"When Listo first saw this photo."}]}},"required":["photo_url","captured_at"],"isRequired":true,"uniqueKey":"oneOf.0.data.proofs.pickup.oneOf.1","typeLabel":"null"}],"isRequired":true,"uniqueKey":"oneOf.0.data.proofs.pickup","typeLabel":"object | null"},"dropoff":{"oneOf":[{"type":"object","description":"The courier at the customer's door. Present once the order is\ndelivered, or once the attempt left a photo, a signature or a\nsigner there, **including an attempt that failed**: read\n`delivered`, not the presence of a photo, to know whether the\norder was handed over.\n","properties":{"photo_url":{"oneOf":[{"type":"string","format":"uri","description":"Photo taken at the door.","isRequired":true,"uniqueKey":"oneOf.0.data.proofs.dropoff.oneOf.0.photo_url.oneOf.0","typeLabel":"string\u003curi>"},{"type":"null","format":"uri","description":"Photo taken at the door.","isRequired":true,"uniqueKey":"oneOf.0.data.proofs.dropoff.oneOf.0.photo_url.oneOf.1","typeLabel":"null"}],"isRequired":true,"uniqueKey":"oneOf.0.data.proofs.dropoff.oneOf.0.photo_url","typeLabel":"string\u003curi> | null"},"signature_url":{"oneOf":[{"type":"string","format":"uri","description":"Image of the recipient's signature.","isRequired":true,"uniqueKey":"oneOf.0.data.proofs.dropoff.oneOf.0.signature_url.oneOf.0","typeLabel":"string\u003curi>"},{"type":"null","format":"uri","description":"Image of the recipient's signature.","isRequired":true,"uniqueKey":"oneOf.0.data.proofs.dropoff.oneOf.0.signature_url.oneOf.1","typeLabel":"null"}],"isRequired":true,"uniqueKey":"oneOf.0.data.proofs.dropoff.oneOf.0.signature_url","typeLabel":"string\u003curi> | null"},"signer_name":{"oneOf":[{"type":"string","description":"The name the person who signed typed.","isRequired":true,"uniqueKey":"oneOf.0.data.proofs.dropoff.oneOf.0.signer_name.oneOf.0","typeLabel":"string"},{"type":"null","description":"The name the person who signed typed.","isRequired":true,"uniqueKey":"oneOf.0.data.proofs.dropoff.oneOf.0.signer_name.oneOf.1","typeLabel":"null"}],"isRequired":true,"uniqueKey":"oneOf.0.data.proofs.dropoff.oneOf.0.signer_name","typeLabel":"string | null"},"captured_at":{"oneOf":[{"type":"string","format":"date-time","description":"When Listo first saw this evidence.","isRequired":true,"uniqueKey":"oneOf.0.data.proofs.dropoff.oneOf.0.captured_at.oneOf.0","typeLabel":"string\u003cdate-time>"},{"type":"null","format":"date-time","description":"When Listo first saw this evidence.","isRequired":true,"uniqueKey":"oneOf.0.data.proofs.dropoff.oneOf.0.captured_at.oneOf.1","typeLabel":"null"}],"isRequired":true,"uniqueKey":"oneOf.0.data.proofs.dropoff.oneOf.0.captured_at","typeLabel":"string\u003cdate-time> | null"},"delivered":{"type":"boolean","description":"True only when the delivery was delivered. False means the\nevidence is from an attempt that did not hand the order over.\n","isRequired":true,"uniqueKey":"oneOf.0.data.proofs.dropoff.oneOf.0.delivered","typeLabel":"boolean"}},"required":["photo_url","signature_url","signer_name","captured_at","delivered"],"isRequired":true,"uniqueKey":"oneOf.0.data.proofs.dropoff.oneOf.0","typeLabel":"object"},{"type":"null","description":"The courier at the customer's door. Present once the order is\ndelivered, or once the attempt left a photo, a signature or a\nsigner there, **including an attempt that failed**: read\n`delivered`, not the presence of a photo, to know whether the\norder was handed over.\n","properties":{"photo_url":{"oneOf":[{"type":"string","format":"uri","description":"Photo taken at the door."},{"type":"null","format":"uri","description":"Photo taken at the door."}]},"signature_url":{"oneOf":[{"type":"string","format":"uri","description":"Image of the recipient's signature."},{"type":"null","format":"uri","description":"Image of the recipient's signature."}]},"signer_name":{"oneOf":[{"type":"string","description":"The name the person who signed typed."},{"type":"null","description":"The name the person who signed typed."}]},"captured_at":{"oneOf":[{"type":"string","format":"date-time","description":"When Listo first saw this evidence."},{"type":"null","format":"date-time","description":"When Listo first saw this evidence."}]},"delivered":{"type":"boolean","description":"True only when the delivery was delivered. False means the\nevidence is from an attempt that did not hand the order over.\n"}},"required":["photo_url","signature_url","signer_name","captured_at","delivered"],"isRequired":true,"uniqueKey":"oneOf.0.data.proofs.dropoff.oneOf.1","typeLabel":"null"}],"isRequired":true,"uniqueKey":"oneOf.0.data.proofs.dropoff","typeLabel":"object | null"},"return":{"oneOf":[{"type":"object","description":"The courier handing the order back at the store after a failed\ndelivery. Null unless the order came back with evidence.\n","properties":{"photo_url":{"oneOf":[{"type":"string","format":"uri","description":"Photo of the order handed back at the store.","isRequired":true,"uniqueKey":"oneOf.0.data.proofs.return.oneOf.0.photo_url.oneOf.0","typeLabel":"string\u003curi>"},{"type":"null","format":"uri","description":"Photo of the order handed back at the store.","isRequired":true,"uniqueKey":"oneOf.0.data.proofs.return.oneOf.0.photo_url.oneOf.1","typeLabel":"null"}],"isRequired":true,"uniqueKey":"oneOf.0.data.proofs.return.oneOf.0.photo_url","typeLabel":"string\u003curi> | null"},"signature_url":{"oneOf":[{"type":"string","format":"uri","description":"Image of the signature of whoever received it at the store.","isRequired":true,"uniqueKey":"oneOf.0.data.proofs.return.oneOf.0.signature_url.oneOf.0","typeLabel":"string\u003curi>"},{"type":"null","format":"uri","description":"Image of the signature of whoever received it at the store.","isRequired":true,"uniqueKey":"oneOf.0.data.proofs.return.oneOf.0.signature_url.oneOf.1","typeLabel":"null"}],"isRequired":true,"uniqueKey":"oneOf.0.data.proofs.return.oneOf.0.signature_url","typeLabel":"string\u003curi> | null"},"signer_name":{"oneOf":[{"type":"string","description":"The name the person who signed typed.","isRequired":true,"uniqueKey":"oneOf.0.data.proofs.return.oneOf.0.signer_name.oneOf.0","typeLabel":"string"},{"type":"null","description":"The name the person who signed typed.","isRequired":true,"uniqueKey":"oneOf.0.data.proofs.return.oneOf.0.signer_name.oneOf.1","typeLabel":"null"}],"isRequired":true,"uniqueKey":"oneOf.0.data.proofs.return.oneOf.0.signer_name","typeLabel":"string | null"},"captured_at":{"oneOf":[{"type":"string","format":"date-time","description":"When Listo first saw this evidence.","isRequired":true,"uniqueKey":"oneOf.0.data.proofs.return.oneOf.0.captured_at.oneOf.0","typeLabel":"string\u003cdate-time>"},{"type":"null","format":"date-time","description":"When Listo first saw this evidence.","isRequired":true,"uniqueKey":"oneOf.0.data.proofs.return.oneOf.0.captured_at.oneOf.1","typeLabel":"null"}],"isRequired":true,"uniqueKey":"oneOf.0.data.proofs.return.oneOf.0.captured_at","typeLabel":"string\u003cdate-time> | null"},"meters_from_store":{"oneOf":[{"type":"integer","description":"How far from the store the courier was when this was\ncaptured, in whole metres in a straight line. Null when\neither position is unknown. Evidence for a person to read,\nnot a verdict.\n","isRequired":true,"uniqueKey":"oneOf.0.data.proofs.return.oneOf.0.meters_from_store.oneOf.0","typeLabel":"integer"},{"type":"null","description":"How far from the store the courier was when this was\ncaptured, in whole metres in a straight line. Null when\neither position is unknown. Evidence for a person to read,\nnot a verdict.\n","isRequired":true,"uniqueKey":"oneOf.0.data.proofs.return.oneOf.0.meters_from_store.oneOf.1","typeLabel":"null"}],"isRequired":true,"uniqueKey":"oneOf.0.data.proofs.return.oneOf.0.meters_from_store","typeLabel":"integer | null"}},"required":["photo_url","signature_url","signer_name","captured_at","meters_from_store"],"isRequired":true,"uniqueKey":"oneOf.0.data.proofs.return.oneOf.0","typeLabel":"object"},{"type":"null","description":"The courier handing the order back at the store after a failed\ndelivery. Null unless the order came back with evidence.\n","properties":{"photo_url":{"oneOf":[{"type":"string","format":"uri","description":"Photo of the order handed back at the store."},{"type":"null","format":"uri","description":"Photo of the order handed back at the store."}]},"signature_url":{"oneOf":[{"type":"string","format":"uri","description":"Image of the signature of whoever received it at the store."},{"type":"null","format":"uri","description":"Image of the signature of whoever received it at the store."}]},"signer_name":{"oneOf":[{"type":"string","description":"The name the person who signed typed."},{"type":"null","description":"The name the person who signed typed."}]},"captured_at":{"oneOf":[{"type":"string","format":"date-time","description":"When Listo first saw this evidence."},{"type":"null","format":"date-time","description":"When Listo first saw this evidence."}]},"meters_from_store":{"oneOf":[{"type":"integer","description":"How far from the store the courier was when this was\ncaptured, in whole metres in a straight line. Null when\neither position is unknown. Evidence for a person to read,\nnot a verdict.\n"},{"type":"null","description":"How far from the store the courier was when this was\ncaptured, in whole metres in a straight line. Null when\neither position is unknown. Evidence for a person to read,\nnot a verdict.\n"}]}},"required":["photo_url","signature_url","signer_name","captured_at","meters_from_store"],"isRequired":true,"uniqueKey":"oneOf.0.data.proofs.return.oneOf.1","typeLabel":"null"}],"isRequired":true,"uniqueKey":"oneOf.0.data.proofs.return","typeLabel":"object | null"}},"required":["pickup","dropoff","return"],"isRequired":true,"uniqueKey":"oneOf.0.data.proofs","typeLabel":"object"},"cancellation":{"oneOf":[{"type":"object","description":"Who called the order off, and why. Null on an order that was not cancelled.","properties":{"party":{"type":"string","enum":["partner","courier","platform"],"description":"`partner` is you. `courier` is the person carrying it.\n`platform` is us, and it also covers a cancellation reported to\nus on the customer's behalf: the end customer is not an actor in\nthis API, so this field never names a person you cannot\ncorrelate.\n","isRequired":true,"uniqueKey":"oneOf.0.data.cancellation.oneOf.0.party","typeLabel":"enum\u003cstring>"},"reason":{"oneOf":[{"type":"string","enum":["customer_canceled","store_closed","item_unavailable","wrong_address","no_longer_needed","other",null],"description":"The reason you sent on a cancel. Null when the attribution was\nderived rather than given, which is every cancellation you did\nnot make.\n","isRequired":true,"uniqueKey":"oneOf.0.data.cancellation.oneOf.0.reason.oneOf.0","typeLabel":"enum\u003cstring>"},{"type":"null","enum":["customer_canceled","store_closed","item_unavailable","wrong_address","no_longer_needed","other",null],"description":"The reason you sent on a cancel. Null when the attribution was\nderived rather than given, which is every cancellation you did\nnot make.\n","isRequired":true,"uniqueKey":"oneOf.0.data.cancellation.oneOf.0.reason.oneOf.1","typeLabel":"null"}],"isRequired":true,"uniqueKey":"oneOf.0.data.cancellation.oneOf.0.reason","typeLabel":"enum\u003cstring> | null"},"description":{"oneOf":[{"type":"string","isRequired":true,"uniqueKey":"oneOf.0.data.cancellation.oneOf.0.description.oneOf.0","typeLabel":"string"},{"type":"null","isRequired":true,"uniqueKey":"oneOf.0.data.cancellation.oneOf.0.description.oneOf.1","typeLabel":"null"}],"isRequired":true,"uniqueKey":"oneOf.0.data.cancellation.oneOf.0.description","typeLabel":"string | null"}},"required":["party","reason","description"],"isRequired":true,"uniqueKey":"oneOf.0.data.cancellation.oneOf.0","typeLabel":"object"},{"type":"null","description":"Who called the order off, and why. Null on an order that was not cancelled.","properties":{"party":{"type":"string","enum":["partner","courier","platform"],"description":"`partner` is you. `courier` is the person carrying it.\n`platform` is us, and it also covers a cancellation reported to\nus on the customer's behalf: the end customer is not an actor in\nthis API, so this field never names a person you cannot\ncorrelate.\n"},"reason":{"oneOf":[{"type":"string","enum":["customer_canceled","store_closed","item_unavailable","wrong_address","no_longer_needed","other",null],"description":"The reason you sent on a cancel. Null when the attribution was\nderived rather than given, which is every cancellation you did\nnot make.\n"},{"type":"null","enum":["customer_canceled","store_closed","item_unavailable","wrong_address","no_longer_needed","other",null],"description":"The reason you sent on a cancel. Null when the attribution was\nderived rather than given, which is every cancellation you did\nnot make.\n"}]},"description":{"oneOf":[{"type":"string"},{"type":"null"}]}},"required":["party","reason","description"],"isRequired":true,"uniqueKey":"oneOf.0.data.cancellation.oneOf.1","typeLabel":"null"}],"isRequired":true,"uniqueKey":"oneOf.0.data.cancellation","typeLabel":"object | null"},"failure_reason":{"oneOf":[{"type":"string","enum":["no_couriers_available","address_unreachable","customer_unavailable","delivery_failed",null],"description":"Why a dispatch failed, bucketed by whose side the problem is on, so\nyou can act on it rather than just retry blindly.\n`no_couriers_available` is the retriable one.\n`delivery_failed` is the honest catch-all. Null unless a failure was\nrecorded.\n","isRequired":true,"uniqueKey":"oneOf.0.data.failure_reason.oneOf.0","typeLabel":"enum\u003cstring>"},{"type":"null","enum":["no_couriers_available","address_unreachable","customer_unavailable","delivery_failed",null],"description":"Why a dispatch failed, bucketed by whose side the problem is on, so\nyou can act on it rather than just retry blindly.\n`no_couriers_available` is the retriable one.\n`delivery_failed` is the honest catch-all. Null unless a failure was\nrecorded.\n","isRequired":true,"uniqueKey":"oneOf.0.data.failure_reason.oneOf.1","typeLabel":"null"}],"isRequired":true,"uniqueKey":"oneOf.0.data.failure_reason","typeLabel":"enum\u003cstring> | null"},"charges":{"type":"array","description":"What a trip that was driven but wasted was billed at: the delivery\nfee for each leg driven, less your own store markup. Empty on\nalmost every delivery, and never null.\n\n**This amount changed on 2026-08-29.** It used to be what the\nwasted trip cost Listo, so expect larger values on the same orders\nfrom that date onward. The field itself is unchanged.\n\nAlways present on a delivery object, so treat an absent `charges`\nas impossible rather than as \"no charges\". It is in this schema's\n`required` list for that reason.\n\nA charge can arrive on the delivery's final\n`delivery.status_changed` or, when the cost settles afterwards, on\na later `delivery.updated`. You cannot assume which, so read this\non both: billing the moment a delivery reaches its terminal status\nbills short on every order whose cost landed late.\n\nThe same movement appears on `GET /v1/ledger` as a signed row, so\nit reads negative there while `amount_cents` here is positive.\n","items":{"type":"object","properties":{"type":{"type":"string","enum":["cancellation_fee","return_fee"],"description":"What the charge was for. `cancellation_fee` is a\ncancellation late enough that a courier was already working\non the order. `return_fee` is a return trip after a failed\ndropoff, and it bills as ONE entry covering both legs of the\njourney rather than two.\n","isRequired":true,"uniqueKey":"oneOf.0.data.charges.items.[INDEX].type","typeLabel":"enum\u003cstring>"},"amount_cents":{"type":"integer","description":"What you were charged, positive, in Mexican peso cents: the\ndelivery fee for each leg that was driven, less your own\nstore markup.\n","isRequired":true,"uniqueKey":"oneOf.0.data.charges.items.[INDEX].amount_cents","typeLabel":"integer"},"charged_at":{"type":"string","format":"date-time","description":"When the charge was recorded, which is not when the delivery\nended.\n","isRequired":true,"uniqueKey":"oneOf.0.data.charges.items.[INDEX].charged_at","typeLabel":"string\u003cdate-time>"}},"required":["type","amount_cents","charged_at"],"uniqueKey":"oneOf.0.data.charges.items.[INDEX]","typeLabel":"object"},"isRequired":true,"uniqueKey":"oneOf.0.data.charges","typeLabel":"object[]"},"refunds":{"type":"array","description":"Every time money went back to the customer on this order, newest\nfirst. Empty on an order that has never been refunded, and never\nnull.\n\nAlways present on a delivery object, so treat an absent `refunds`\nas impossible rather than as \"no refunds\". It is in this schema's\n`required` list for that reason, exactly as `charges` above is.\n\nIt is a LIST because refunds repeat: a partial refund is followed\nby another refund, each with its own amount, its own reason and its\nown outcome. Every refund we can see is here whoever made it, which\nis what makes the list worth reconciling against. The connected\naccount belongs to the merchant of record, which can refund a charge\non it without going through us at all; those arrive as\n`requested_via: external`, and a list that showed only the refunds\nyou asked for would silently disagree with this order's own\n`payment.status`.\n\nA refund rides `delivery.updated`, never an event of its own.\n","items":{"type":"object","properties":{"id":{"type":"string","description":"The refund id, `rfn_` prefixed.","example":"rfn_4bQ7wS2xK9mT6vN3cZ8pLdYe","isRequired":true,"uniqueKey":"oneOf.0.data.refunds.items.[INDEX].id","typeLabel":"string"},"amount_cents":{"oneOf":[{"type":"integer","description":"What went back, positive, in Mexican peso cents. NULL AND NOT\nZERO while a refund of the remaining balance is still in\nflight: it carries no amount until the refund is confirmed,\nand a zero would say a refund moved nothing. Read\n`refunded_cents` below rather than summing this array, which\nis exactly why both totals are published.\n","isRequired":true,"uniqueKey":"oneOf.0.data.refunds.items.[INDEX].amount_cents.oneOf.0","typeLabel":"integer"},{"type":"null","description":"What went back, positive, in Mexican peso cents. NULL AND NOT\nZERO while a refund of the remaining balance is still in\nflight: it carries no amount until the refund is confirmed,\nand a zero would say a refund moved nothing. Read\n`refunded_cents` below rather than summing this array, which\nis exactly why both totals are published.\n","isRequired":true,"uniqueKey":"oneOf.0.data.refunds.items.[INDEX].amount_cents.oneOf.1","typeLabel":"null"}],"isRequired":true,"uniqueKey":"oneOf.0.data.refunds.items.[INDEX].amount_cents","typeLabel":"integer | null"},"reason":{"oneOf":[{"type":"string","description":"The free text whoever asked for the refund supplied, or null.\nYour own words when you sent them; it is never an enum.\n","isRequired":true,"uniqueKey":"oneOf.0.data.refunds.items.[INDEX].reason.oneOf.0","typeLabel":"string"},{"type":"null","description":"The free text whoever asked for the refund supplied, or null.\nYour own words when you sent them; it is never an enum.\n","isRequired":true,"uniqueKey":"oneOf.0.data.refunds.items.[INDEX].reason.oneOf.1","typeLabel":"null"}],"isRequired":true,"uniqueKey":"oneOf.0.data.refunds.items.[INDEX].reason","typeLabel":"string | null"},"status":{"type":"string","enum":["pending","succeeded","failed"],"description":"`pending` IS NOT A FAILURE and must not be retried: a\ndirect-charge refund is held while the account's balance is\nshort and applied once funds land. It flips to `succeeded` on\nits own and publishes that as `delivery.updated`. `failed`\nmeans nothing moved.\n","isRequired":true,"uniqueKey":"oneOf.0.data.refunds.items.[INDEX].status","typeLabel":"enum\u003cstring>"},"requested_via":{"type":"string","enum":["api","console","automatic","external"],"description":"Which lane issued it. `api` is your own\n`POST /v1/deliveries/{id}/refunds`. `console` is the merchant\npressing it in the Listo console. `automatic` is one we issued\nwith nobody asking, on a cancel or a return. `external` is one\nmade in the merchant's own payment dashboard, which we learned\nabout afterwards.\n","isRequired":true,"uniqueKey":"oneOf.0.data.refunds.items.[INDEX].requested_via","typeLabel":"enum\u003cstring>"},"party":{"type":"string","enum":["business","platform"],"description":"Whose decision it was. `business` is the merchant, or you\nacting for your store. `platform` is Listo issuing it because\nthe order ended without reaching the customer.\n","isRequired":true,"uniqueKey":"oneOf.0.data.refunds.items.[INDEX].party","typeLabel":"enum\u003cstring>"},"created_at":{"type":"string","format":"date-time","description":"When the refund was asked for.","isRequired":true,"uniqueKey":"oneOf.0.data.refunds.items.[INDEX].created_at","typeLabel":"string\u003cdate-time>"},"succeeded_at":{"oneOf":[{"type":"string","format":"date-time","description":"When the money was confirmed on its way. Null on a pending or\nfailed refund.\n","isRequired":true,"uniqueKey":"oneOf.0.data.refunds.items.[INDEX].succeeded_at.oneOf.0","typeLabel":"string\u003cdate-time>"},{"type":"null","format":"date-time","description":"When the money was confirmed on its way. Null on a pending or\nfailed refund.\n","isRequired":true,"uniqueKey":"oneOf.0.data.refunds.items.[INDEX].succeeded_at.oneOf.1","typeLabel":"null"}],"isRequired":true,"uniqueKey":"oneOf.0.data.refunds.items.[INDEX].succeeded_at","typeLabel":"string\u003cdate-time> | null"}},"required":["id","amount_cents","reason","status","requested_via","party","created_at","succeeded_at"],"uniqueKey":"oneOf.0.data.refunds.items.[INDEX]","typeLabel":"object"},"isRequired":true,"uniqueKey":"oneOf.0.data.refunds","typeLabel":"object[]"},"refunded_cents":{"type":"integer","description":"The sum of the SUCCEEDED refunds above, in Mexican peso cents. 0,\nnever null, on an order nothing has gone back on. A `pending` refund\nis not counted, because the money has not moved and may yet be\nrefused.\n\nPublished rather than left for you to compute, because the array\ncannot always be summed correctly: a refund of the remaining balance\ncarries no `amount_cents` until it is confirmed, so adding the\nlist up counts it as zero and reads the whole charge as still\nrefundable. We take that case pessimistically instead, as having\ntaken the entire remaining balance, because guessing low ends in\nrefunding a customer twice.\n","isRequired":true,"uniqueKey":"oneOf.0.data.refunded_cents","typeLabel":"integer"},"refundable_cents":{"type":"integer","description":"What a further refund could still return: what the customer paid\n(`order_value_cents` plus `customer_fee_cents`, which IS the charge)\nminus `refunded_cents`, floored at zero. 0, never null.\n\n0 on any order with no collected card payment behind it, whatever\nits value. Cash never touched our rails, a prepaid order's customer\nis yours and we hold nothing of theirs, and an order still awaiting\npayment was never charged, so there is nothing on any of them a\nrefund could return.\n\nThis is the ceiling `POST /v1/deliveries/{id}/refunds` refuses an\n`amount_cents` against, so read it before you call rather than\ndiscovering the bound from a `refund_amount_too_large`.\n","isRequired":true,"uniqueKey":"oneOf.0.data.refundable_cents","typeLabel":"integer"},"support_reference":{"oneOf":[{"type":"string","description":"A short handle to quote when you escalate an order to us. Null until\nthe order reaches dispatch.\n","example":"2080F","isRequired":true,"uniqueKey":"oneOf.0.data.support_reference.oneOf.0","typeLabel":"string"},{"type":"null","description":"A short handle to quote when you escalate an order to us. Null until\nthe order reaches dispatch.\n","example":"2080F","isRequired":true,"uniqueKey":"oneOf.0.data.support_reference.oneOf.1","typeLabel":"null"}],"isRequired":true,"uniqueKey":"oneOf.0.data.support_reference","typeLabel":"string | null"},"pickup_ready_at":{"oneOf":[{"type":"string","format":"date-time","description":"The scheduled pickup time you asked for. Null on a dispatch-now order.","isRequired":true,"uniqueKey":"oneOf.0.data.pickup_ready_at.oneOf.0","typeLabel":"string\u003cdate-time>"},{"type":"null","format":"date-time","description":"The scheduled pickup time you asked for. Null on a dispatch-now order.","isRequired":true,"uniqueKey":"oneOf.0.data.pickup_ready_at.oneOf.1","typeLabel":"null"}],"isRequired":true,"uniqueKey":"oneOf.0.data.pickup_ready_at","typeLabel":"string\u003cdate-time> | null"},"requested_at":{"oneOf":[{"type":"string","format":"date-time","isRequired":true,"uniqueKey":"oneOf.0.data.requested_at.oneOf.0","typeLabel":"string\u003cdate-time>"},{"type":"null","format":"date-time","isRequired":true,"uniqueKey":"oneOf.0.data.requested_at.oneOf.1","typeLabel":"null"}],"isRequired":true,"uniqueKey":"oneOf.0.data.requested_at","typeLabel":"string\u003cdate-time> | null"},"courier_assigned_at":{"oneOf":[{"type":"string","format":"date-time","description":"When a courier was first observed on the current attempt. Honestly\nan observation rather than an assignment clock, because no\nassignment time is published to us. Null on an attempt that never\nhad one.\n","isRequired":true,"uniqueKey":"oneOf.0.data.courier_assigned_at.oneOf.0","typeLabel":"string\u003cdate-time>"},{"type":"null","format":"date-time","description":"When a courier was first observed on the current attempt. Honestly\nan observation rather than an assignment clock, because no\nassignment time is published to us. Null on an attempt that never\nhad one.\n","isRequired":true,"uniqueKey":"oneOf.0.data.courier_assigned_at.oneOf.1","typeLabel":"null"}],"isRequired":true,"uniqueKey":"oneOf.0.data.courier_assigned_at","typeLabel":"string\u003cdate-time> | null"},"picked_up_at":{"oneOf":[{"type":"string","format":"date-time","isRequired":true,"uniqueKey":"oneOf.0.data.picked_up_at.oneOf.0","typeLabel":"string\u003cdate-time>"},{"type":"null","format":"date-time","isRequired":true,"uniqueKey":"oneOf.0.data.picked_up_at.oneOf.1","typeLabel":"null"}],"isRequired":true,"uniqueKey":"oneOf.0.data.picked_up_at","typeLabel":"string\u003cdate-time> | null"},"delivered_at":{"oneOf":[{"type":"string","format":"date-time","isRequired":true,"uniqueKey":"oneOf.0.data.delivered_at.oneOf.0","typeLabel":"string\u003cdate-time>"},{"type":"null","format":"date-time","isRequired":true,"uniqueKey":"oneOf.0.data.delivered_at.oneOf.1","typeLabel":"null"}],"isRequired":true,"uniqueKey":"oneOf.0.data.delivered_at","typeLabel":"string\u003cdate-time> | null"},"canceled_at":{"oneOf":[{"type":"string","format":"date-time","isRequired":true,"uniqueKey":"oneOf.0.data.canceled_at.oneOf.0","typeLabel":"string\u003cdate-time>"},{"type":"null","format":"date-time","isRequired":true,"uniqueKey":"oneOf.0.data.canceled_at.oneOf.1","typeLabel":"null"}],"isRequired":true,"uniqueKey":"oneOf.0.data.canceled_at","typeLabel":"string\u003cdate-time> | null"},"returned_at":{"oneOf":[{"type":"string","format":"date-time","isRequired":true,"uniqueKey":"oneOf.0.data.returned_at.oneOf.0","typeLabel":"string\u003cdate-time>"},{"type":"null","format":"date-time","isRequired":true,"uniqueKey":"oneOf.0.data.returned_at.oneOf.1","typeLabel":"null"}],"isRequired":true,"uniqueKey":"oneOf.0.data.returned_at","typeLabel":"string\u003cdate-time> | null"},"created_at":{"type":"string","format":"date-time","isRequired":true,"uniqueKey":"oneOf.0.data.created_at","typeLabel":"string\u003cdate-time>"},"updated_at":{"type":"string","format":"date-time","isRequired":true,"uniqueKey":"oneOf.0.data.updated_at","typeLabel":"string\u003cdate-time>"}},"required":["id","external_id","origin","code","status","store_id","test","payment","order_value_cents","fee_cents","business_fee_cents","customer_fee_cents","tip_cents","currency","quote_id","pickup","dropoff","manifest","vehicle","courier","pickup_eta_at","dropoff_eta_at","tracking_url","verification","return_verification","proof","proofs","cancellation","failure_reason","support_reference","pickup_ready_at","requested_at","courier_assigned_at","picked_up_at","delivered_at","canceled_at","returned_at","created_at","updated_at","charges","refunds","refunded_cents","refundable_cents"],"isRequired":true,"uniqueKey":"oneOf.0.data","typeLabel":"object"},"test":{"type":"boolean","description":"Present, and true, only on a test event you asked for with\n`POST /v1/test_webhooks`. A real event does not carry the field at\nall. A test event's `data` is a sample whose ids resolve to nothing.\n","example":true,"uniqueKey":"oneOf.0.test","typeLabel":"boolean"}},"uniqueKey":"oneOf.0","typeLabel":"object"},{"type":"object","description":"Every event your webhook endpoint receives, and every event the\ndebugging reads return: one of the six below, told apart by `type`.\n`data` is the object the event is about, and its shape depends on\n`type`. See `WebhookEventEnvelope` for the fields they all share and for\nhow delivery behaves (at-least-once, unordered).\n","required":["type","data","id","created_at"],"properties":{"id":{"type":"string","description":"The event id, `evt_` prefixed. Dedupe on this.","example":"evt_9pQ2vX7mKdR4tYb1nZ3sLwCe","isRequired":true,"uniqueKey":"oneOf.1.id","typeLabel":"string"},"created_at":{"type":"string","format":"date-time","description":"When the event was recorded, ISO-8601 in UTC.","example":"2026-07-28T18:41:03Z","isRequired":true,"uniqueKey":"oneOf.1.created_at","typeLabel":"string\u003cdate-time>"},"type":{"type":"string","description":"Which event this is.","enum":["delivery.updated"],"isRequired":true,"uniqueKey":"oneOf.1.type","typeLabel":"enum\u003cstring>"},"data":{"type":"object","description":"The shape of a delivery: every field the object can carry, with the\nnullability each one really has. It is the response of every operation\nthat answers a delivery (the create, the fetch, a list row, the\nreschedule, the cancel, the retry and the refund) and the `data` of\nevery full delivery event, so ONE type holds all of them.\n\nEvery operation returns the whole object. A field that a given call\ncannot yet have is present and null rather than missing: a create\nresponse has a null `courier`, because no courier has been assigned\nyet, and a reschedule only ever answers with a still-scheduled order,\nso its `delivered_at` is null.\n\nMoney is integer centavos, timestamps are ISO-8601 in UTC, and every\nenum below is ours rather than a passthrough of anyone else's.\n","properties":{"id":{"type":"string","description":"The delivery id, `dlv_` prefixed.","example":"dlv_7hK2mQ9xR4tV6bN1cZ8sLwYe","isRequired":true,"uniqueKey":"oneOf.1.data.id","typeLabel":"string"},"external_id":{"oneOf":[{"type":"string","description":"Your own order reference, echoed back exactly as you sent it.","example":"order-841","isRequired":true,"uniqueKey":"oneOf.1.data.external_id.oneOf.0","typeLabel":"string"},{"type":"null","description":"Your own order reference, echoed back exactly as you sent it.","example":"order-841","isRequired":true,"uniqueKey":"oneOf.1.data.external_id.oneOf.1","typeLabel":"null"}],"isRequired":true,"uniqueKey":"oneOf.1.data.external_id","typeLabel":"string | null"},"origin":{"type":"string","enum":["api","console","whatsapp"],"description":"Which lane created the delivery. `api` is one you created through\n`POST /v1/deliveries`. `console` is one the store dispatched itself\nfrom the Listo merchant console, which a store can do only at the\n`full` access tier. `whatsapp` is one a customer ordered from the\nstore in a chat, which the store then accepted; no operator typed\nit anywhere.\n\nAlways present, never null, and fixed for the life of the delivery.\nA console order carries a null `external_id`, but read this field\nrather than that null: the missing reference is a consequence of the\nlane, not a way of identifying it.\n","example":"api","isRequired":true,"uniqueKey":"oneOf.1.data.origin","typeLabel":"enum\u003cstring>"},"code":{"type":"string","description":"The human order code the courier and our support quote. Unique per\nstore, not globally, so never address an order by it.\n","example":"LS-2048","isRequired":true,"uniqueKey":"oneOf.1.data.code","typeLabel":"string"},"status":{"type":"string","enum":["awaiting_payment","awaiting_location","scheduled","dispatching","courier_assigned","picking_up","en_route","returning","delivered","returned","canceled","no_courier"],"description":"`delivered`, `returned` and `canceled` are terminal. `no_courier` is\na dead end you can retry or cancel. A `returned` delivery is this\nsame object throughout; there is no second delivery for the return\nleg.\n\n`returning`: the drop-off failed and the courier is bringing the\norder back to the store; it ends in `returned`. It is NOT terminal,\nand it is where a failed delivery now spends the minutes between the\ncourier giving up at the customer's door and the order actually\narriving back. `returned` means the order is back. Treat `returning`\nas a live delivery: the courier is still moving and\n`delivery.courier_location` events keep arriving for it.\n\nThe return charge is posted when the delivery enters `returning`,\nnot when it reaches `returned`, so `charges` is already complete on\nthe `returning` event.\n\n`awaiting_location`: an order the store took through Listo's console\nor its WhatsApp assistant, held for the drop-off location. No\ncourier is requested yet. The customer confirms the location on a\nmap link or by sharing it in the WhatsApp chat, or the store\nconfirms it from its console. The delivery then moves to\n`scheduled` or `dispatching`; to `no_courier` when a courier\ncannot be requested for it (the location is outside where the\nstore delivers, or the store itself cannot request a courier right\nnow); or to `canceled` if the order is canceled or the store\nchanges it to a pickup at the counter. A delivery you create\nthrough this API never sits in it.\n","isRequired":true,"uniqueKey":"oneOf.1.data.status","typeLabel":"enum\u003cstring>"},"store_id":{"type":"string","description":"The `st_` id of the store the courier collects from.","isRequired":true,"uniqueKey":"oneOf.1.data.store_id","typeLabel":"string"},"test":{"type":"boolean","description":"Whether this order lives in the sandbox. Derived from the store, so\nthere is no field to set: a test key can only reach test stores.\n","isRequired":true,"uniqueKey":"oneOf.1.data.test","typeLabel":"boolean"},"payment":{"type":"object","description":"How the customer pays, and where that got to.","properties":{"method":{"type":"string","enum":["prepaid","cash","card"],"isRequired":true,"uniqueKey":"oneOf.1.data.payment.method","typeLabel":"enum\u003cstring>"},"status":{"type":"string","enum":["unpaid","awaiting_payment","paid","partially_refunded","refunded"],"isRequired":true,"uniqueKey":"oneOf.1.data.payment.status","typeLabel":"enum\u003cstring>"},"url":{"oneOf":[{"type":"string","format":"uri","description":"The branded payment link for a card order still awaiting\npayment. Listo sends it to your customer itself, by WhatsApp\nand by SMS when the WhatsApp does not reach them, so you can\nshow it or keep it but need not send it. Null the moment the\norder is paid or cancelled, because the link is then dead.\n","isRequired":true,"uniqueKey":"oneOf.1.data.payment.url.oneOf.0","typeLabel":"string\u003curi>"},{"type":"null","format":"uri","description":"The branded payment link for a card order still awaiting\npayment. Listo sends it to your customer itself, by WhatsApp\nand by SMS when the WhatsApp does not reach them, so you can\nshow it or keep it but need not send it. Null the moment the\norder is paid or cancelled, because the link is then dead.\n","isRequired":true,"uniqueKey":"oneOf.1.data.payment.url.oneOf.1","typeLabel":"null"}],"isRequired":true,"uniqueKey":"oneOf.1.data.payment.url","typeLabel":"string\u003curi> | null"},"cash_to_collect_cents":{"oneOf":[{"type":"integer","description":"What the courier collects at the door: the goods value plus the\ncustomer's share of the fee. Null, not zero, on any order that\nis not cash. Zero is a real value on a cash order whose door\ntotal is zero (a `0` order value you fully cover); such an order\nis dispatched with no collection to make.\n","isRequired":true,"uniqueKey":"oneOf.1.data.payment.cash_to_collect_cents.oneOf.0","typeLabel":"integer"},{"type":"null","description":"What the courier collects at the door: the goods value plus the\ncustomer's share of the fee. Null, not zero, on any order that\nis not cash. Zero is a real value on a cash order whose door\ntotal is zero (a `0` order value you fully cover); such an order\nis dispatched with no collection to make.\n","isRequired":true,"uniqueKey":"oneOf.1.data.payment.cash_to_collect_cents.oneOf.1","typeLabel":"null"}],"isRequired":true,"uniqueKey":"oneOf.1.data.payment.cash_to_collect_cents","typeLabel":"integer | null"},"paid_at":{"oneOf":[{"type":"string","format":"date-time","isRequired":true,"uniqueKey":"oneOf.1.data.payment.paid_at.oneOf.0","typeLabel":"string\u003cdate-time>"},{"type":"null","format":"date-time","isRequired":true,"uniqueKey":"oneOf.1.data.payment.paid_at.oneOf.1","typeLabel":"null"}],"isRequired":true,"uniqueKey":"oneOf.1.data.payment.paid_at","typeLabel":"string\u003cdate-time> | null"}},"required":["method","status","url","cash_to_collect_cents","paid_at"],"isRequired":true,"uniqueKey":"oneOf.1.data.payment","typeLabel":"object"},"order_value_cents":{"oneOf":[{"type":"integer","description":"The goods value you sent, untouched.","isRequired":true,"uniqueKey":"oneOf.1.data.order_value_cents.oneOf.0","typeLabel":"integer"},{"type":"null","description":"The goods value you sent, untouched.","isRequired":true,"uniqueKey":"oneOf.1.data.order_value_cents.oneOf.1","typeLabel":"null"}],"isRequired":true,"uniqueKey":"oneOf.1.data.order_value_cents","typeLabel":"integer | null"},"fee_cents":{"type":"integer","description":"The total delivery fee.","isRequired":true,"uniqueKey":"oneOf.1.data.fee_cents","typeLabel":"integer"},"business_fee_cents":{"type":"integer","description":"The part of `fee_cents` charged to you.","isRequired":true,"uniqueKey":"oneOf.1.data.business_fee_cents","typeLabel":"integer"},"customer_fee_cents":{"type":"integer","description":"The part of `fee_cents` charged to the customer. Always sums with\n`business_fee_cents` back to `fee_cents`.\n","isRequired":true,"uniqueKey":"oneOf.1.data.customer_fee_cents","typeLabel":"integer"},"tip_cents":{"type":"integer","description":"The courier tip you sent on this delivery, paid to the courier and\npassed on at cost with no margin taken. Deliberately OUTSIDE\n`fee_cents`, which is the delivery fee `business_fee_cents` and\n`customer_fee_cents` sum back to. 0 when you sent none, and never\nnull.\n","isRequired":true,"uniqueKey":"oneOf.1.data.tip_cents","typeLabel":"integer"},"currency":{"type":"string","enum":["MXN"],"isRequired":true,"uniqueKey":"oneOf.1.data.currency","typeLabel":"enum\u003cstring>"},"quote_id":{"oneOf":[{"type":"string","description":"The `qt_` quote this order bound, so you can tie the price you were\nquoted to the order that spent it. Null when the order was priced\ninline instead.\n","isRequired":true,"uniqueKey":"oneOf.1.data.quote_id.oneOf.0","typeLabel":"string"},{"type":"null","description":"The `qt_` quote this order bound, so you can tie the price you were\nquoted to the order that spent it. Null when the order was priced\ninline instead.\n","isRequired":true,"uniqueKey":"oneOf.1.data.quote_id.oneOf.1","typeLabel":"null"}],"isRequired":true,"uniqueKey":"oneOf.1.data.quote_id","typeLabel":"string | null"},"pickup":{"type":"object","description":"Where the courier collects, snapshotted at create, so a historical\norder keeps reporting where the courier actually went even after the\nstore is renamed or moved.\n","properties":{"name":{"type":"string","isRequired":true,"uniqueKey":"oneOf.1.data.pickup.name","typeLabel":"string"},"street":{"type":"string","isRequired":true,"uniqueKey":"oneOf.1.data.pickup.street","typeLabel":"string"},"lat":{"oneOf":[{"type":"number","format":"double","isRequired":true,"uniqueKey":"oneOf.1.data.pickup.lat.oneOf.0","typeLabel":"number\u003cdouble>"},{"type":"null","format":"double","isRequired":true,"uniqueKey":"oneOf.1.data.pickup.lat.oneOf.1","typeLabel":"null"}],"isRequired":true,"uniqueKey":"oneOf.1.data.pickup.lat","typeLabel":"number\u003cdouble> | null"},"lng":{"oneOf":[{"type":"number","format":"double","isRequired":true,"uniqueKey":"oneOf.1.data.pickup.lng.oneOf.0","typeLabel":"number\u003cdouble>"},{"type":"null","format":"double","isRequired":true,"uniqueKey":"oneOf.1.data.pickup.lng.oneOf.1","typeLabel":"null"}],"isRequired":true,"uniqueKey":"oneOf.1.data.pickup.lng","typeLabel":"number\u003cdouble> | null"},"notes":{"oneOf":[{"type":"string","description":"The store's standing pickup instructions, not a per-order value.","isRequired":true,"uniqueKey":"oneOf.1.data.pickup.notes.oneOf.0","typeLabel":"string"},{"type":"null","description":"The store's standing pickup instructions, not a per-order value.","isRequired":true,"uniqueKey":"oneOf.1.data.pickup.notes.oneOf.1","typeLabel":"null"}],"isRequired":true,"uniqueKey":"oneOf.1.data.pickup.notes","typeLabel":"string | null"}},"required":["name","street","lat","lng","notes"],"isRequired":true,"uniqueKey":"oneOf.1.data.pickup","typeLabel":"object"},"dropoff":{"type":"object","description":"Where the courier delivers, echoed back as you sent it.","properties":{"name":{"type":"string","isRequired":true,"uniqueKey":"oneOf.1.data.dropoff.name","typeLabel":"string"},"phone":{"type":"string","description":"E.164, normalized on the way in.","example":"+528112345678","isRequired":true,"uniqueKey":"oneOf.1.data.dropoff.phone","typeLabel":"string"},"street":{"type":"string","isRequired":true,"uniqueKey":"oneOf.1.data.dropoff.street","typeLabel":"string"},"apt_unit":{"oneOf":[{"type":"string","isRequired":true,"uniqueKey":"oneOf.1.data.dropoff.apt_unit.oneOf.0","typeLabel":"string"},{"type":"null","isRequired":true,"uniqueKey":"oneOf.1.data.dropoff.apt_unit.oneOf.1","typeLabel":"null"}],"isRequired":true,"uniqueKey":"oneOf.1.data.dropoff.apt_unit","typeLabel":"string | null"},"lat":{"oneOf":[{"type":"number","format":"double","description":"Null when the address was never geocoded and the text was judged\ninstead. Never a fabricated zero.\n","isRequired":true,"uniqueKey":"oneOf.1.data.dropoff.lat.oneOf.0","typeLabel":"number\u003cdouble>"},{"type":"null","format":"double","description":"Null when the address was never geocoded and the text was judged\ninstead. Never a fabricated zero.\n","isRequired":true,"uniqueKey":"oneOf.1.data.dropoff.lat.oneOf.1","typeLabel":"null"}],"isRequired":true,"uniqueKey":"oneOf.1.data.dropoff.lat","typeLabel":"number\u003cdouble> | null"},"lng":{"oneOf":[{"type":"number","format":"double","isRequired":true,"uniqueKey":"oneOf.1.data.dropoff.lng.oneOf.0","typeLabel":"number\u003cdouble>"},{"type":"null","format":"double","isRequired":true,"uniqueKey":"oneOf.1.data.dropoff.lng.oneOf.1","typeLabel":"null"}],"isRequired":true,"uniqueKey":"oneOf.1.data.dropoff.lng","typeLabel":"number\u003cdouble> | null"},"notes":{"oneOf":[{"type":"string","isRequired":true,"uniqueKey":"oneOf.1.data.dropoff.notes.oneOf.0","typeLabel":"string"},{"type":"null","isRequired":true,"uniqueKey":"oneOf.1.data.dropoff.notes.oneOf.1","typeLabel":"null"}],"isRequired":true,"uniqueKey":"oneOf.1.data.dropoff.notes","typeLabel":"string | null"},"handoff":{"type":"string","enum":["meet_at_door","leave_at_door","meet_outside"],"isRequired":true,"uniqueKey":"oneOf.1.data.dropoff.handoff","typeLabel":"enum\u003cstring>"}},"required":["name","phone","street","apt_unit","lat","lng","notes","handoff"],"isRequired":true,"uniqueKey":"oneOf.1.data.dropoff","typeLabel":"object"},"manifest":{"oneOf":[{"type":"object","description":"The descriptive item list you sent, for the courier. Money never\ncomes from it, with one exception: an item sized `xlarge` makes the\ntrip a car. Null when you sent none.\n","properties":{"items":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string","isRequired":true,"uniqueKey":"oneOf.1.data.manifest.oneOf.0.\\items.items.[INDEX].name","typeLabel":"string"},"quantity":{"type":"integer","isRequired":true,"uniqueKey":"oneOf.1.data.manifest.oneOf.0.\\items.items.[INDEX].quantity","typeLabel":"integer"},"size":{"type":"string","enum":["small","medium","large","xlarge"],"description":"What the item was sent as. `small` when you sent none,\nand on every item created before sizes existed, which is\nwhat those items were sent as.\n","isRequired":true,"uniqueKey":"oneOf.1.data.manifest.oneOf.0.\\items.items.[INDEX].size","typeLabel":"enum\u003cstring>"}},"required":["name","quantity","size"],"uniqueKey":"oneOf.1.data.manifest.oneOf.0.\\items.items.[INDEX]","typeLabel":"object"},"isRequired":true,"uniqueKey":"oneOf.1.data.manifest.oneOf.0.\\items","typeLabel":"object[]"}},"required":["items"],"isRequired":true,"uniqueKey":"oneOf.1.data.manifest.oneOf.0","typeLabel":"object"},{"type":"null","description":"The descriptive item list you sent, for the courier. Money never\ncomes from it, with one exception: an item sized `xlarge` makes the\ntrip a car. Null when you sent none.\n","properties":{"items":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string"},"quantity":{"type":"integer"},"size":{"type":"string","enum":["small","medium","large","xlarge"],"description":"What the item was sent as. `small` when you sent none,\nand on every item created before sizes existed, which is\nwhat those items were sent as.\n"}},"required":["name","quantity","size"]}}},"required":["items"],"isRequired":true,"uniqueKey":"oneOf.1.data.manifest.oneOf.1","typeLabel":"null"}],"isRequired":true,"uniqueKey":"oneOf.1.data.manifest","typeLabel":"object | null"},"vehicle":{"type":"string","enum":["moto","car"],"description":"What the trip was priced and dispatched as: `car` when you asked for\none or when an item was sized `xlarge`, `moto` otherwise. A car's\nsurcharge is inside `fee_cents`. Always present, never null, and\nfixed for the life of the delivery.\n\nNot the vehicle that arrived. That is `courier.vehicle_type`, which\ncan be a car on a `moto` trip without the fee changing.\n","example":"moto","isRequired":true,"uniqueKey":"oneOf.1.data.vehicle","typeLabel":"enum\u003cstring>"},"courier":{"oneOf":[{"type":"object","description":"Null until a courier is assigned, and then FROZEN: a terminal\ndelivery keeps reporting who carried it.\n","properties":{"name":{"type":"string","isRequired":true,"uniqueKey":"oneOf.1.data.courier.oneOf.0.name","typeLabel":"string"},"vehicle":{"oneOf":[{"type":"string","description":"What the courier is riding, in English whatever locale the\nrequest carried (\"Motorcycle\", \"Bicycle\"). Derived from\n`vehicle_type`, so it is null exactly when that is: display it,\nand switch on `vehicle_type` instead.\n","isRequired":true,"uniqueKey":"oneOf.1.data.courier.oneOf.0.vehicle.oneOf.0","typeLabel":"string"},{"type":"null","description":"What the courier is riding, in English whatever locale the\nrequest carried (\"Motorcycle\", \"Bicycle\"). Derived from\n`vehicle_type`, so it is null exactly when that is: display it,\nand switch on `vehicle_type` instead.\n","isRequired":true,"uniqueKey":"oneOf.1.data.courier.oneOf.0.vehicle.oneOf.1","typeLabel":"null"}],"isRequired":true,"uniqueKey":"oneOf.1.data.courier.oneOf.0.vehicle","typeLabel":"string | null"},"vehicle_type":{"oneOf":[{"type":"string","description":"The machine-readable type: `bicycle`, `car`, `van`, `truck`,\n`scooter`, `motorcycle` or `walker`. Null until the courier is\nassigned a vehicle. Treat an unlisted value as unknown rather\nthan an error: this list grows.\n","isRequired":true,"uniqueKey":"oneOf.1.data.courier.oneOf.0.vehicle_type.oneOf.0","typeLabel":"string"},{"type":"null","description":"The machine-readable type: `bicycle`, `car`, `van`, `truck`,\n`scooter`, `motorcycle` or `walker`. Null until the courier is\nassigned a vehicle. Treat an unlisted value as unknown rather\nthan an error: this list grows.\n","isRequired":true,"uniqueKey":"oneOf.1.data.courier.oneOf.0.vehicle_type.oneOf.1","typeLabel":"null"}],"isRequired":true,"uniqueKey":"oneOf.1.data.courier.oneOf.0.vehicle_type","typeLabel":"string | null"},"plate":{"oneOf":[{"type":"string","isRequired":true,"uniqueKey":"oneOf.1.data.courier.oneOf.0.plate.oneOf.0","typeLabel":"string"},{"type":"null","isRequired":true,"uniqueKey":"oneOf.1.data.courier.oneOf.0.plate.oneOf.1","typeLabel":"null"}],"isRequired":true,"uniqueKey":"oneOf.1.data.courier.oneOf.0.plate","typeLabel":"string | null"},"phone":{"oneOf":[{"type":"object","description":"A masked number and its IVR PIN, never a personal number. Dial\n`masked` and enter `pin` when the system asks. Null when no\nnumber has been issued for this courier.\n","properties":{"masked":{"type":"string","isRequired":true,"uniqueKey":"oneOf.1.data.courier.oneOf.0.phone.oneOf.0.masked","typeLabel":"string"},"pin":{"oneOf":[{"type":"string","isRequired":true,"uniqueKey":"oneOf.1.data.courier.oneOf.0.phone.oneOf.0.pin.oneOf.0","typeLabel":"string"},{"type":"null","isRequired":true,"uniqueKey":"oneOf.1.data.courier.oneOf.0.phone.oneOf.0.pin.oneOf.1","typeLabel":"null"}],"isRequired":true,"uniqueKey":"oneOf.1.data.courier.oneOf.0.phone.oneOf.0.pin","typeLabel":"string | null"}},"required":["masked","pin"],"isRequired":true,"uniqueKey":"oneOf.1.data.courier.oneOf.0.phone.oneOf.0","typeLabel":"object"},{"type":"null","description":"A masked number and its IVR PIN, never a personal number. Dial\n`masked` and enter `pin` when the system asks. Null when no\nnumber has been issued for this courier.\n","properties":{"masked":{"type":"string"},"pin":{"oneOf":[{"type":"string"},{"type":"null"}]}},"required":["masked","pin"],"isRequired":true,"uniqueKey":"oneOf.1.data.courier.oneOf.0.phone.oneOf.1","typeLabel":"null"}],"isRequired":true,"uniqueKey":"oneOf.1.data.courier.oneOf.0.phone","typeLabel":"object | null"},"location":{"oneOf":[{"type":"object","description":"The live position, present only while the courier is actually in\nmotion and only once there is a real fix.\n","properties":{"lat":{"type":"number","format":"double","isRequired":true,"uniqueKey":"oneOf.1.data.courier.oneOf.0.location.oneOf.0.lat","typeLabel":"number\u003cdouble>"},"lng":{"type":"number","format":"double","isRequired":true,"uniqueKey":"oneOf.1.data.courier.oneOf.0.location.oneOf.0.lng","typeLabel":"number\u003cdouble>"},"updated_at":{"oneOf":[{"type":"string","format":"date-time","isRequired":true,"uniqueKey":"oneOf.1.data.courier.oneOf.0.location.oneOf.0.updated_at.oneOf.0","typeLabel":"string\u003cdate-time>"},{"type":"null","format":"date-time","isRequired":true,"uniqueKey":"oneOf.1.data.courier.oneOf.0.location.oneOf.0.updated_at.oneOf.1","typeLabel":"null"}],"isRequired":true,"uniqueKey":"oneOf.1.data.courier.oneOf.0.location.oneOf.0.updated_at","typeLabel":"string\u003cdate-time> | null"}},"required":["lat","lng","updated_at"],"isRequired":true,"uniqueKey":"oneOf.1.data.courier.oneOf.0.location.oneOf.0","typeLabel":"object"},{"type":"null","description":"The live position, present only while the courier is actually in\nmotion and only once there is a real fix.\n","properties":{"lat":{"type":"number","format":"double"},"lng":{"type":"number","format":"double"},"updated_at":{"oneOf":[{"type":"string","format":"date-time"},{"type":"null","format":"date-time"}]}},"required":["lat","lng","updated_at"],"isRequired":true,"uniqueKey":"oneOf.1.data.courier.oneOf.0.location.oneOf.1","typeLabel":"null"}],"isRequired":true,"uniqueKey":"oneOf.1.data.courier.oneOf.0.location","typeLabel":"object | null"},"imminent":{"type":"boolean","description":"The courier is about a minute away. Always false once the trip ends.","isRequired":true,"uniqueKey":"oneOf.1.data.courier.oneOf.0.imminent","typeLabel":"boolean"}},"required":["name","vehicle","vehicle_type","plate","phone","location","imminent"],"isRequired":true,"uniqueKey":"oneOf.1.data.courier.oneOf.0","typeLabel":"object"},{"type":"null","description":"Null until a courier is assigned, and then FROZEN: a terminal\ndelivery keeps reporting who carried it.\n","properties":{"name":{"type":"string"},"vehicle":{"oneOf":[{"type":"string","description":"What the courier is riding, in English whatever locale the\nrequest carried (\"Motorcycle\", \"Bicycle\"). Derived from\n`vehicle_type`, so it is null exactly when that is: display it,\nand switch on `vehicle_type` instead.\n"},{"type":"null","description":"What the courier is riding, in English whatever locale the\nrequest carried (\"Motorcycle\", \"Bicycle\"). Derived from\n`vehicle_type`, so it is null exactly when that is: display it,\nand switch on `vehicle_type` instead.\n"}]},"vehicle_type":{"oneOf":[{"type":"string","description":"The machine-readable type: `bicycle`, `car`, `van`, `truck`,\n`scooter`, `motorcycle` or `walker`. Null until the courier is\nassigned a vehicle. Treat an unlisted value as unknown rather\nthan an error: this list grows.\n"},{"type":"null","description":"The machine-readable type: `bicycle`, `car`, `van`, `truck`,\n`scooter`, `motorcycle` or `walker`. Null until the courier is\nassigned a vehicle. Treat an unlisted value as unknown rather\nthan an error: this list grows.\n"}]},"plate":{"oneOf":[{"type":"string"},{"type":"null"}]},"phone":{"oneOf":[{"type":"object","description":"A masked number and its IVR PIN, never a personal number. Dial\n`masked` and enter `pin` when the system asks. Null when no\nnumber has been issued for this courier.\n","properties":{"masked":{"type":"string"},"pin":{"oneOf":[{"type":"string"},{"type":"null"}]}},"required":["masked","pin"]},{"type":"null","description":"A masked number and its IVR PIN, never a personal number. Dial\n`masked` and enter `pin` when the system asks. Null when no\nnumber has been issued for this courier.\n","properties":{"masked":{"type":"string"},"pin":{"oneOf":[{"type":"string"},{"type":"null"}]}},"required":["masked","pin"]}]},"location":{"oneOf":[{"type":"object","description":"The live position, present only while the courier is actually in\nmotion and only once there is a real fix.\n","properties":{"lat":{"type":"number","format":"double"},"lng":{"type":"number","format":"double"},"updated_at":{"oneOf":[{"type":"string","format":"date-time"},{"type":"null","format":"date-time"}]}},"required":["lat","lng","updated_at"]},{"type":"null","description":"The live position, present only while the courier is actually in\nmotion and only once there is a real fix.\n","properties":{"lat":{"type":"number","format":"double"},"lng":{"type":"number","format":"double"},"updated_at":{"oneOf":[{"type":"string","format":"date-time"},{"type":"null","format":"date-time"}]}},"required":["lat","lng","updated_at"]}]},"imminent":{"type":"boolean","description":"The courier is about a minute away. Always false once the trip ends."}},"required":["name","vehicle","vehicle_type","plate","phone","location","imminent"],"isRequired":true,"uniqueKey":"oneOf.1.data.courier.oneOf.1","typeLabel":"null"}],"isRequired":true,"uniqueKey":"oneOf.1.data.courier","typeLabel":"object | null"},"pickup_eta_at":{"oneOf":[{"type":"string","format":"date-time","description":"When the courier is expected at the store. Absolute, so you compute\nyour own countdown; a countdown computed here is stale before you\nread it.\n","isRequired":true,"uniqueKey":"oneOf.1.data.pickup_eta_at.oneOf.0","typeLabel":"string\u003cdate-time>"},{"type":"null","format":"date-time","description":"When the courier is expected at the store. Absolute, so you compute\nyour own countdown; a countdown computed here is stale before you\nread it.\n","isRequired":true,"uniqueKey":"oneOf.1.data.pickup_eta_at.oneOf.1","typeLabel":"null"}],"isRequired":true,"uniqueKey":"oneOf.1.data.pickup_eta_at","typeLabel":"string\u003cdate-time> | null"},"dropoff_eta_at":{"oneOf":[{"type":"string","format":"date-time","description":"When the courier is expected at the customer. Null until there is\nan estimate, and null again once the drop-off has failed\n(`returning`, `returned`): the courier is then bringing the order\nback to the store, there is no arrival at the customer left to\ndescribe, and the time it gets back to the store is never published\nhere.\n","isRequired":true,"uniqueKey":"oneOf.1.data.dropoff_eta_at.oneOf.0","typeLabel":"string\u003cdate-time>"},{"type":"null","format":"date-time","description":"When the courier is expected at the customer. Null until there is\nan estimate, and null again once the drop-off has failed\n(`returning`, `returned`): the courier is then bringing the order\nback to the store, there is no arrival at the customer left to\ndescribe, and the time it gets back to the store is never published\nhere.\n","isRequired":true,"uniqueKey":"oneOf.1.data.dropoff_eta_at.oneOf.1","typeLabel":"null"}],"isRequired":true,"uniqueKey":"oneOf.1.data.dropoff_eta_at","typeLabel":"string\u003cdate-time> | null"},"tracking_url":{"oneOf":[{"type":"string","format":"uri","description":"The branded live tracking page for the customer: the map, the\ncourier, the delivery code and what is owed at the door. Null when\nthere is no page to point at, so you never relay a dead link.\n\nThere is a page from the moment the order is dispatched, including\nthe whole window before a courier is assigned, and for 48 hours\nafter the order is delivered, canceled or returned. It is null while\nan order is still held awaiting payment or awaiting a confirmed\ndrop-off pin, and null again once that 48 hours has passed.\n","example":"https://app.listo.delivery/t/abc123","isRequired":true,"uniqueKey":"oneOf.1.data.tracking_url.oneOf.0","typeLabel":"string\u003curi>"},{"type":"null","format":"uri","description":"The branded live tracking page for the customer: the map, the\ncourier, the delivery code and what is owed at the door. Null when\nthere is no page to point at, so you never relay a dead link.\n\nThere is a page from the moment the order is dispatched, including\nthe whole window before a courier is assigned, and for 48 hours\nafter the order is delivered, canceled or returned. It is null while\nan order is still held awaiting payment or awaiting a confirmed\ndrop-off pin, and null again once that 48 hours has passed.\n","example":"https://app.listo.delivery/t/abc123","isRequired":true,"uniqueKey":"oneOf.1.data.tracking_url.oneOf.1","typeLabel":"null"}],"isRequired":true,"uniqueKey":"oneOf.1.data.tracking_url","typeLabel":"string\u003curi> | null"},"verification":{"oneOf":[{"type":"object","description":"Present only when the order carries a dropoff PIN: when you asked\nfor one (`verification.dropoff_pincode` on the create), or when\nListo requires a PIN on every delivery of this store's account, in\nwhich case it is present even though you did not ask. `pincode` is\nnull until the order is actually dispatched, which is when the code\nis minted.\n","properties":{"pincode":{"oneOf":[{"type":"string","isRequired":true,"uniqueKey":"oneOf.1.data.verification.oneOf.0.pincode.oneOf.0","typeLabel":"string"},{"type":"null","isRequired":true,"uniqueKey":"oneOf.1.data.verification.oneOf.0.pincode.oneOf.1","typeLabel":"null"}],"isRequired":true,"uniqueKey":"oneOf.1.data.verification.oneOf.0.pincode","typeLabel":"string | null"}},"required":["pincode"],"isRequired":true,"uniqueKey":"oneOf.1.data.verification.oneOf.0","typeLabel":"object"},{"type":"null","description":"Present only when the order carries a dropoff PIN: when you asked\nfor one (`verification.dropoff_pincode` on the create), or when\nListo requires a PIN on every delivery of this store's account, in\nwhich case it is present even though you did not ask. `pincode` is\nnull until the order is actually dispatched, which is when the code\nis minted.\n","properties":{"pincode":{"oneOf":[{"type":"string"},{"type":"null"}]}},"required":["pincode"],"isRequired":true,"uniqueKey":"oneOf.1.data.verification.oneOf.1","typeLabel":"null"}],"isRequired":true,"uniqueKey":"oneOf.1.data.verification","typeLabel":"object | null"},"return_verification":{"type":"object","description":"The return code (código de devolución). When an order cannot be\ndelivered and the courier brings it back to the store, the courier\nmust be given this code at the store to hand the order over; without\nit the return cannot be completed. `pincode` is a 4-digit string\nwhile the delivery is `returning`, and null in every other state\n(before the return, and once it is `returned`). The object is\nalways present, so this field never needs a presence check. It\narrives in `delivery.status_changed` (the move into `returning`) and\nin `delivery.updated`, which carry the whole object. A new attempt\n(a retry) gets its own code. Show it to the store, and never to the\ncustomer.\n","properties":{"pincode":{"oneOf":[{"type":"string","example":"4821","isRequired":true,"uniqueKey":"oneOf.1.data.return_verification.pincode.oneOf.0","typeLabel":"string"},{"type":"null","example":"4821","isRequired":true,"uniqueKey":"oneOf.1.data.return_verification.pincode.oneOf.1","typeLabel":"null"}],"isRequired":true,"uniqueKey":"oneOf.1.data.return_verification.pincode","typeLabel":"string | null"}},"required":["pincode"],"isRequired":true,"uniqueKey":"oneOf.1.data.return_verification","typeLabel":"object"},"proof":{"oneOf":[{"type":"object","description":"Proof of delivery. Null unless we hold some, and each field is null\nwhen that piece is missing; a photo with no signature is normal. The\nURLs are Listo's own signed links to the stored copy and are valid\nfor 24 hours from the response (or webhook) that carried them:\nfetch `GET /v1/deliveries/{id}` again for a fresh link, or keep a\ncopy. **A URL is null until Listo has its own copy of the image**\n(a few seconds after the courier takes it); the copy's arrival is\nannounced by a `delivery.updated` webhook that carries the link.\nIt may come from a delivery attempt that failed at the\ndoor, so it is not by itself proof that the order was handed over:\n`proofs.dropoff.delivered` says which. Prefer `proofs`, which keeps\neach moment of the trip apart.\n","properties":{"picture_url":{"oneOf":[{"type":"string","format":"uri","isRequired":true,"uniqueKey":"oneOf.1.data.proof.oneOf.0.picture_url.oneOf.0","typeLabel":"string\u003curi>"},{"type":"null","format":"uri","isRequired":true,"uniqueKey":"oneOf.1.data.proof.oneOf.0.picture_url.oneOf.1","typeLabel":"null"}],"isRequired":true,"uniqueKey":"oneOf.1.data.proof.oneOf.0.picture_url","typeLabel":"string\u003curi> | null"},"signature_image_url":{"oneOf":[{"type":"string","format":"uri","isRequired":true,"uniqueKey":"oneOf.1.data.proof.oneOf.0.signature_image_url.oneOf.0","typeLabel":"string\u003curi>"},{"type":"null","format":"uri","isRequired":true,"uniqueKey":"oneOf.1.data.proof.oneOf.0.signature_image_url.oneOf.1","typeLabel":"null"}],"isRequired":true,"uniqueKey":"oneOf.1.data.proof.oneOf.0.signature_image_url","typeLabel":"string\u003curi> | null"},"signature_name":{"oneOf":[{"type":"string","isRequired":true,"uniqueKey":"oneOf.1.data.proof.oneOf.0.signature_name.oneOf.0","typeLabel":"string"},{"type":"null","isRequired":true,"uniqueKey":"oneOf.1.data.proof.oneOf.0.signature_name.oneOf.1","typeLabel":"null"}],"isRequired":true,"uniqueKey":"oneOf.1.data.proof.oneOf.0.signature_name","typeLabel":"string | null"},"captured_at":{"oneOf":[{"type":"string","format":"date-time","isRequired":true,"uniqueKey":"oneOf.1.data.proof.oneOf.0.captured_at.oneOf.0","typeLabel":"string\u003cdate-time>"},{"type":"null","format":"date-time","isRequired":true,"uniqueKey":"oneOf.1.data.proof.oneOf.0.captured_at.oneOf.1","typeLabel":"null"}],"isRequired":true,"uniqueKey":"oneOf.1.data.proof.oneOf.0.captured_at","typeLabel":"string\u003cdate-time> | null"}},"required":["picture_url","signature_image_url","signature_name","captured_at"],"isRequired":true,"uniqueKey":"oneOf.1.data.proof.oneOf.0","typeLabel":"object"},{"type":"null","description":"Proof of delivery. Null unless we hold some, and each field is null\nwhen that piece is missing; a photo with no signature is normal. The\nURLs are Listo's own signed links to the stored copy and are valid\nfor 24 hours from the response (or webhook) that carried them:\nfetch `GET /v1/deliveries/{id}` again for a fresh link, or keep a\ncopy. **A URL is null until Listo has its own copy of the image**\n(a few seconds after the courier takes it); the copy's arrival is\nannounced by a `delivery.updated` webhook that carries the link.\nIt may come from a delivery attempt that failed at the\ndoor, so it is not by itself proof that the order was handed over:\n`proofs.dropoff.delivered` says which. Prefer `proofs`, which keeps\neach moment of the trip apart.\n","properties":{"picture_url":{"oneOf":[{"type":"string","format":"uri"},{"type":"null","format":"uri"}]},"signature_image_url":{"oneOf":[{"type":"string","format":"uri"},{"type":"null","format":"uri"}]},"signature_name":{"oneOf":[{"type":"string"},{"type":"null"}]},"captured_at":{"oneOf":[{"type":"string","format":"date-time"},{"type":"null","format":"date-time"}]}},"required":["picture_url","signature_image_url","signature_name","captured_at"],"isRequired":true,"uniqueKey":"oneOf.1.data.proof.oneOf.1","typeLabel":"null"}],"isRequired":true,"uniqueKey":"oneOf.1.data.proof","typeLabel":"object | null"},"proofs":{"type":"object","description":"The evidence the trip left, one entry per moment. Each moment is\nnull until it happens (nothing has been captured for it yet), so\nthis object is always present with its three keys. A photo or\nsignature link is Listo's own signed link to the stored copy, and\n**it is null until Listo holds that copy** (a few seconds after the\ncourier takes the photo): the rest of the moment, the signer, the\ntime and the distance, is there from the start, and when the copy\nlands a `delivery.updated` webhook carries the link. **Each link is\nvalid for 24 hours** from the response (or webhook) that carried\nit: it is a short-lived signed link, never a permanent one. A\npartner that needs the image later fetches\n`GET /v1/deliveries/{id}` again for a fresh link, or keeps a copy.\n","properties":{"pickup":{"oneOf":[{"type":"object","description":"The courier collecting the order at the store. Null until the\npickup photo exists.\n","properties":{"photo_url":{"oneOf":[{"type":"string","format":"uri","description":"Photo of the order at the store.","isRequired":true,"uniqueKey":"oneOf.1.data.proofs.pickup.oneOf.0.photo_url.oneOf.0","typeLabel":"string\u003curi>"},{"type":"null","format":"uri","description":"Photo of the order at the store.","isRequired":true,"uniqueKey":"oneOf.1.data.proofs.pickup.oneOf.0.photo_url.oneOf.1","typeLabel":"null"}],"isRequired":true,"uniqueKey":"oneOf.1.data.proofs.pickup.oneOf.0.photo_url","typeLabel":"string\u003curi> | null"},"captured_at":{"oneOf":[{"type":"string","format":"date-time","description":"When Listo first saw this photo.","isRequired":true,"uniqueKey":"oneOf.1.data.proofs.pickup.oneOf.0.captured_at.oneOf.0","typeLabel":"string\u003cdate-time>"},{"type":"null","format":"date-time","description":"When Listo first saw this photo.","isRequired":true,"uniqueKey":"oneOf.1.data.proofs.pickup.oneOf.0.captured_at.oneOf.1","typeLabel":"null"}],"isRequired":true,"uniqueKey":"oneOf.1.data.proofs.pickup.oneOf.0.captured_at","typeLabel":"string\u003cdate-time> | null"}},"required":["photo_url","captured_at"],"isRequired":true,"uniqueKey":"oneOf.1.data.proofs.pickup.oneOf.0","typeLabel":"object"},{"type":"null","description":"The courier collecting the order at the store. Null until the\npickup photo exists.\n","properties":{"photo_url":{"oneOf":[{"type":"string","format":"uri","description":"Photo of the order at the store."},{"type":"null","format":"uri","description":"Photo of the order at the store."}]},"captured_at":{"oneOf":[{"type":"string","format":"date-time","description":"When Listo first saw this photo."},{"type":"null","format":"date-time","description":"When Listo first saw this photo."}]}},"required":["photo_url","captured_at"],"isRequired":true,"uniqueKey":"oneOf.1.data.proofs.pickup.oneOf.1","typeLabel":"null"}],"isRequired":true,"uniqueKey":"oneOf.1.data.proofs.pickup","typeLabel":"object | null"},"dropoff":{"oneOf":[{"type":"object","description":"The courier at the customer's door. Present once the order is\ndelivered, or once the attempt left a photo, a signature or a\nsigner there, **including an attempt that failed**: read\n`delivered`, not the presence of a photo, to know whether the\norder was handed over.\n","properties":{"photo_url":{"oneOf":[{"type":"string","format":"uri","description":"Photo taken at the door.","isRequired":true,"uniqueKey":"oneOf.1.data.proofs.dropoff.oneOf.0.photo_url.oneOf.0","typeLabel":"string\u003curi>"},{"type":"null","format":"uri","description":"Photo taken at the door.","isRequired":true,"uniqueKey":"oneOf.1.data.proofs.dropoff.oneOf.0.photo_url.oneOf.1","typeLabel":"null"}],"isRequired":true,"uniqueKey":"oneOf.1.data.proofs.dropoff.oneOf.0.photo_url","typeLabel":"string\u003curi> | null"},"signature_url":{"oneOf":[{"type":"string","format":"uri","description":"Image of the recipient's signature.","isRequired":true,"uniqueKey":"oneOf.1.data.proofs.dropoff.oneOf.0.signature_url.oneOf.0","typeLabel":"string\u003curi>"},{"type":"null","format":"uri","description":"Image of the recipient's signature.","isRequired":true,"uniqueKey":"oneOf.1.data.proofs.dropoff.oneOf.0.signature_url.oneOf.1","typeLabel":"null"}],"isRequired":true,"uniqueKey":"oneOf.1.data.proofs.dropoff.oneOf.0.signature_url","typeLabel":"string\u003curi> | null"},"signer_name":{"oneOf":[{"type":"string","description":"The name the person who signed typed.","isRequired":true,"uniqueKey":"oneOf.1.data.proofs.dropoff.oneOf.0.signer_name.oneOf.0","typeLabel":"string"},{"type":"null","description":"The name the person who signed typed.","isRequired":true,"uniqueKey":"oneOf.1.data.proofs.dropoff.oneOf.0.signer_name.oneOf.1","typeLabel":"null"}],"isRequired":true,"uniqueKey":"oneOf.1.data.proofs.dropoff.oneOf.0.signer_name","typeLabel":"string | null"},"captured_at":{"oneOf":[{"type":"string","format":"date-time","description":"When Listo first saw this evidence.","isRequired":true,"uniqueKey":"oneOf.1.data.proofs.dropoff.oneOf.0.captured_at.oneOf.0","typeLabel":"string\u003cdate-time>"},{"type":"null","format":"date-time","description":"When Listo first saw this evidence.","isRequired":true,"uniqueKey":"oneOf.1.data.proofs.dropoff.oneOf.0.captured_at.oneOf.1","typeLabel":"null"}],"isRequired":true,"uniqueKey":"oneOf.1.data.proofs.dropoff.oneOf.0.captured_at","typeLabel":"string\u003cdate-time> | null"},"delivered":{"type":"boolean","description":"True only when the delivery was delivered. False means the\nevidence is from an attempt that did not hand the order over.\n","isRequired":true,"uniqueKey":"oneOf.1.data.proofs.dropoff.oneOf.0.delivered","typeLabel":"boolean"}},"required":["photo_url","signature_url","signer_name","captured_at","delivered"],"isRequired":true,"uniqueKey":"oneOf.1.data.proofs.dropoff.oneOf.0","typeLabel":"object"},{"type":"null","description":"The courier at the customer's door. Present once the order is\ndelivered, or once the attempt left a photo, a signature or a\nsigner there, **including an attempt that failed**: read\n`delivered`, not the presence of a photo, to know whether the\norder was handed over.\n","properties":{"photo_url":{"oneOf":[{"type":"string","format":"uri","description":"Photo taken at the door."},{"type":"null","format":"uri","description":"Photo taken at the door."}]},"signature_url":{"oneOf":[{"type":"string","format":"uri","description":"Image of the recipient's signature."},{"type":"null","format":"uri","description":"Image of the recipient's signature."}]},"signer_name":{"oneOf":[{"type":"string","description":"The name the person who signed typed."},{"type":"null","description":"The name the person who signed typed."}]},"captured_at":{"oneOf":[{"type":"string","format":"date-time","description":"When Listo first saw this evidence."},{"type":"null","format":"date-time","description":"When Listo first saw this evidence."}]},"delivered":{"type":"boolean","description":"True only when the delivery was delivered. False means the\nevidence is from an attempt that did not hand the order over.\n"}},"required":["photo_url","signature_url","signer_name","captured_at","delivered"],"isRequired":true,"uniqueKey":"oneOf.1.data.proofs.dropoff.oneOf.1","typeLabel":"null"}],"isRequired":true,"uniqueKey":"oneOf.1.data.proofs.dropoff","typeLabel":"object | null"},"return":{"oneOf":[{"type":"object","description":"The courier handing the order back at the store after a failed\ndelivery. Null unless the order came back with evidence.\n","properties":{"photo_url":{"oneOf":[{"type":"string","format":"uri","description":"Photo of the order handed back at the store.","isRequired":true,"uniqueKey":"oneOf.1.data.proofs.return.oneOf.0.photo_url.oneOf.0","typeLabel":"string\u003curi>"},{"type":"null","format":"uri","description":"Photo of the order handed back at the store.","isRequired":true,"uniqueKey":"oneOf.1.data.proofs.return.oneOf.0.photo_url.oneOf.1","typeLabel":"null"}],"isRequired":true,"uniqueKey":"oneOf.1.data.proofs.return.oneOf.0.photo_url","typeLabel":"string\u003curi> | null"},"signature_url":{"oneOf":[{"type":"string","format":"uri","description":"Image of the signature of whoever received it at the store.","isRequired":true,"uniqueKey":"oneOf.1.data.proofs.return.oneOf.0.signature_url.oneOf.0","typeLabel":"string\u003curi>"},{"type":"null","format":"uri","description":"Image of the signature of whoever received it at the store.","isRequired":true,"uniqueKey":"oneOf.1.data.proofs.return.oneOf.0.signature_url.oneOf.1","typeLabel":"null"}],"isRequired":true,"uniqueKey":"oneOf.1.data.proofs.return.oneOf.0.signature_url","typeLabel":"string\u003curi> | null"},"signer_name":{"oneOf":[{"type":"string","description":"The name the person who signed typed.","isRequired":true,"uniqueKey":"oneOf.1.data.proofs.return.oneOf.0.signer_name.oneOf.0","typeLabel":"string"},{"type":"null","description":"The name the person who signed typed.","isRequired":true,"uniqueKey":"oneOf.1.data.proofs.return.oneOf.0.signer_name.oneOf.1","typeLabel":"null"}],"isRequired":true,"uniqueKey":"oneOf.1.data.proofs.return.oneOf.0.signer_name","typeLabel":"string | null"},"captured_at":{"oneOf":[{"type":"string","format":"date-time","description":"When Listo first saw this evidence.","isRequired":true,"uniqueKey":"oneOf.1.data.proofs.return.oneOf.0.captured_at.oneOf.0","typeLabel":"string\u003cdate-time>"},{"type":"null","format":"date-time","description":"When Listo first saw this evidence.","isRequired":true,"uniqueKey":"oneOf.1.data.proofs.return.oneOf.0.captured_at.oneOf.1","typeLabel":"null"}],"isRequired":true,"uniqueKey":"oneOf.1.data.proofs.return.oneOf.0.captured_at","typeLabel":"string\u003cdate-time> | null"},"meters_from_store":{"oneOf":[{"type":"integer","description":"How far from the store the courier was when this was\ncaptured, in whole metres in a straight line. Null when\neither position is unknown. Evidence for a person to read,\nnot a verdict.\n","isRequired":true,"uniqueKey":"oneOf.1.data.proofs.return.oneOf.0.meters_from_store.oneOf.0","typeLabel":"integer"},{"type":"null","description":"How far from the store the courier was when this was\ncaptured, in whole metres in a straight line. Null when\neither position is unknown. Evidence for a person to read,\nnot a verdict.\n","isRequired":true,"uniqueKey":"oneOf.1.data.proofs.return.oneOf.0.meters_from_store.oneOf.1","typeLabel":"null"}],"isRequired":true,"uniqueKey":"oneOf.1.data.proofs.return.oneOf.0.meters_from_store","typeLabel":"integer | null"}},"required":["photo_url","signature_url","signer_name","captured_at","meters_from_store"],"isRequired":true,"uniqueKey":"oneOf.1.data.proofs.return.oneOf.0","typeLabel":"object"},{"type":"null","description":"The courier handing the order back at the store after a failed\ndelivery. Null unless the order came back with evidence.\n","properties":{"photo_url":{"oneOf":[{"type":"string","format":"uri","description":"Photo of the order handed back at the store."},{"type":"null","format":"uri","description":"Photo of the order handed back at the store."}]},"signature_url":{"oneOf":[{"type":"string","format":"uri","description":"Image of the signature of whoever received it at the store."},{"type":"null","format":"uri","description":"Image of the signature of whoever received it at the store."}]},"signer_name":{"oneOf":[{"type":"string","description":"The name the person who signed typed."},{"type":"null","description":"The name the person who signed typed."}]},"captured_at":{"oneOf":[{"type":"string","format":"date-time","description":"When Listo first saw this evidence."},{"type":"null","format":"date-time","description":"When Listo first saw this evidence."}]},"meters_from_store":{"oneOf":[{"type":"integer","description":"How far from the store the courier was when this was\ncaptured, in whole metres in a straight line. Null when\neither position is unknown. Evidence for a person to read,\nnot a verdict.\n"},{"type":"null","description":"How far from the store the courier was when this was\ncaptured, in whole metres in a straight line. Null when\neither position is unknown. Evidence for a person to read,\nnot a verdict.\n"}]}},"required":["photo_url","signature_url","signer_name","captured_at","meters_from_store"],"isRequired":true,"uniqueKey":"oneOf.1.data.proofs.return.oneOf.1","typeLabel":"null"}],"isRequired":true,"uniqueKey":"oneOf.1.data.proofs.return","typeLabel":"object | null"}},"required":["pickup","dropoff","return"],"isRequired":true,"uniqueKey":"oneOf.1.data.proofs","typeLabel":"object"},"cancellation":{"oneOf":[{"type":"object","description":"Who called the order off, and why. Null on an order that was not cancelled.","properties":{"party":{"type":"string","enum":["partner","courier","platform"],"description":"`partner` is you. `courier` is the person carrying it.\n`platform` is us, and it also covers a cancellation reported to\nus on the customer's behalf: the end customer is not an actor in\nthis API, so this field never names a person you cannot\ncorrelate.\n","isRequired":true,"uniqueKey":"oneOf.1.data.cancellation.oneOf.0.party","typeLabel":"enum\u003cstring>"},"reason":{"oneOf":[{"type":"string","enum":["customer_canceled","store_closed","item_unavailable","wrong_address","no_longer_needed","other",null],"description":"The reason you sent on a cancel. Null when the attribution was\nderived rather than given, which is every cancellation you did\nnot make.\n","isRequired":true,"uniqueKey":"oneOf.1.data.cancellation.oneOf.0.reason.oneOf.0","typeLabel":"enum\u003cstring>"},{"type":"null","enum":["customer_canceled","store_closed","item_unavailable","wrong_address","no_longer_needed","other",null],"description":"The reason you sent on a cancel. Null when the attribution was\nderived rather than given, which is every cancellation you did\nnot make.\n","isRequired":true,"uniqueKey":"oneOf.1.data.cancellation.oneOf.0.reason.oneOf.1","typeLabel":"null"}],"isRequired":true,"uniqueKey":"oneOf.1.data.cancellation.oneOf.0.reason","typeLabel":"enum\u003cstring> | null"},"description":{"oneOf":[{"type":"string","isRequired":true,"uniqueKey":"oneOf.1.data.cancellation.oneOf.0.description.oneOf.0","typeLabel":"string"},{"type":"null","isRequired":true,"uniqueKey":"oneOf.1.data.cancellation.oneOf.0.description.oneOf.1","typeLabel":"null"}],"isRequired":true,"uniqueKey":"oneOf.1.data.cancellation.oneOf.0.description","typeLabel":"string | null"}},"required":["party","reason","description"],"isRequired":true,"uniqueKey":"oneOf.1.data.cancellation.oneOf.0","typeLabel":"object"},{"type":"null","description":"Who called the order off, and why. Null on an order that was not cancelled.","properties":{"party":{"type":"string","enum":["partner","courier","platform"],"description":"`partner` is you. `courier` is the person carrying it.\n`platform` is us, and it also covers a cancellation reported to\nus on the customer's behalf: the end customer is not an actor in\nthis API, so this field never names a person you cannot\ncorrelate.\n"},"reason":{"oneOf":[{"type":"string","enum":["customer_canceled","store_closed","item_unavailable","wrong_address","no_longer_needed","other",null],"description":"The reason you sent on a cancel. Null when the attribution was\nderived rather than given, which is every cancellation you did\nnot make.\n"},{"type":"null","enum":["customer_canceled","store_closed","item_unavailable","wrong_address","no_longer_needed","other",null],"description":"The reason you sent on a cancel. Null when the attribution was\nderived rather than given, which is every cancellation you did\nnot make.\n"}]},"description":{"oneOf":[{"type":"string"},{"type":"null"}]}},"required":["party","reason","description"],"isRequired":true,"uniqueKey":"oneOf.1.data.cancellation.oneOf.1","typeLabel":"null"}],"isRequired":true,"uniqueKey":"oneOf.1.data.cancellation","typeLabel":"object | null"},"failure_reason":{"oneOf":[{"type":"string","enum":["no_couriers_available","address_unreachable","customer_unavailable","delivery_failed",null],"description":"Why a dispatch failed, bucketed by whose side the problem is on, so\nyou can act on it rather than just retry blindly.\n`no_couriers_available` is the retriable one.\n`delivery_failed` is the honest catch-all. Null unless a failure was\nrecorded.\n","isRequired":true,"uniqueKey":"oneOf.1.data.failure_reason.oneOf.0","typeLabel":"enum\u003cstring>"},{"type":"null","enum":["no_couriers_available","address_unreachable","customer_unavailable","delivery_failed",null],"description":"Why a dispatch failed, bucketed by whose side the problem is on, so\nyou can act on it rather than just retry blindly.\n`no_couriers_available` is the retriable one.\n`delivery_failed` is the honest catch-all. Null unless a failure was\nrecorded.\n","isRequired":true,"uniqueKey":"oneOf.1.data.failure_reason.oneOf.1","typeLabel":"null"}],"isRequired":true,"uniqueKey":"oneOf.1.data.failure_reason","typeLabel":"enum\u003cstring> | null"},"charges":{"type":"array","description":"What a trip that was driven but wasted was billed at: the delivery\nfee for each leg driven, less your own store markup. Empty on\nalmost every delivery, and never null.\n\n**This amount changed on 2026-08-29.** It used to be what the\nwasted trip cost Listo, so expect larger values on the same orders\nfrom that date onward. The field itself is unchanged.\n\nAlways present on a delivery object, so treat an absent `charges`\nas impossible rather than as \"no charges\". It is in this schema's\n`required` list for that reason.\n\nA charge can arrive on the delivery's final\n`delivery.status_changed` or, when the cost settles afterwards, on\na later `delivery.updated`. You cannot assume which, so read this\non both: billing the moment a delivery reaches its terminal status\nbills short on every order whose cost landed late.\n\nThe same movement appears on `GET /v1/ledger` as a signed row, so\nit reads negative there while `amount_cents` here is positive.\n","items":{"type":"object","properties":{"type":{"type":"string","enum":["cancellation_fee","return_fee"],"description":"What the charge was for. `cancellation_fee` is a\ncancellation late enough that a courier was already working\non the order. `return_fee` is a return trip after a failed\ndropoff, and it bills as ONE entry covering both legs of the\njourney rather than two.\n","isRequired":true,"uniqueKey":"oneOf.1.data.charges.items.[INDEX].type","typeLabel":"enum\u003cstring>"},"amount_cents":{"type":"integer","description":"What you were charged, positive, in Mexican peso cents: the\ndelivery fee for each leg that was driven, less your own\nstore markup.\n","isRequired":true,"uniqueKey":"oneOf.1.data.charges.items.[INDEX].amount_cents","typeLabel":"integer"},"charged_at":{"type":"string","format":"date-time","description":"When the charge was recorded, which is not when the delivery\nended.\n","isRequired":true,"uniqueKey":"oneOf.1.data.charges.items.[INDEX].charged_at","typeLabel":"string\u003cdate-time>"}},"required":["type","amount_cents","charged_at"],"uniqueKey":"oneOf.1.data.charges.items.[INDEX]","typeLabel":"object"},"isRequired":true,"uniqueKey":"oneOf.1.data.charges","typeLabel":"object[]"},"refunds":{"type":"array","description":"Every time money went back to the customer on this order, newest\nfirst. Empty on an order that has never been refunded, and never\nnull.\n\nAlways present on a delivery object, so treat an absent `refunds`\nas impossible rather than as \"no refunds\". It is in this schema's\n`required` list for that reason, exactly as `charges` above is.\n\nIt is a LIST because refunds repeat: a partial refund is followed\nby another refund, each with its own amount, its own reason and its\nown outcome. Every refund we can see is here whoever made it, which\nis what makes the list worth reconciling against. The connected\naccount belongs to the merchant of record, which can refund a charge\non it without going through us at all; those arrive as\n`requested_via: external`, and a list that showed only the refunds\nyou asked for would silently disagree with this order's own\n`payment.status`.\n\nA refund rides `delivery.updated`, never an event of its own.\n","items":{"type":"object","properties":{"id":{"type":"string","description":"The refund id, `rfn_` prefixed.","example":"rfn_4bQ7wS2xK9mT6vN3cZ8pLdYe","isRequired":true,"uniqueKey":"oneOf.1.data.refunds.items.[INDEX].id","typeLabel":"string"},"amount_cents":{"oneOf":[{"type":"integer","description":"What went back, positive, in Mexican peso cents. NULL AND NOT\nZERO while a refund of the remaining balance is still in\nflight: it carries no amount until the refund is confirmed,\nand a zero would say a refund moved nothing. Read\n`refunded_cents` below rather than summing this array, which\nis exactly why both totals are published.\n","isRequired":true,"uniqueKey":"oneOf.1.data.refunds.items.[INDEX].amount_cents.oneOf.0","typeLabel":"integer"},{"type":"null","description":"What went back, positive, in Mexican peso cents. NULL AND NOT\nZERO while a refund of the remaining balance is still in\nflight: it carries no amount until the refund is confirmed,\nand a zero would say a refund moved nothing. Read\n`refunded_cents` below rather than summing this array, which\nis exactly why both totals are published.\n","isRequired":true,"uniqueKey":"oneOf.1.data.refunds.items.[INDEX].amount_cents.oneOf.1","typeLabel":"null"}],"isRequired":true,"uniqueKey":"oneOf.1.data.refunds.items.[INDEX].amount_cents","typeLabel":"integer | null"},"reason":{"oneOf":[{"type":"string","description":"The free text whoever asked for the refund supplied, or null.\nYour own words when you sent them; it is never an enum.\n","isRequired":true,"uniqueKey":"oneOf.1.data.refunds.items.[INDEX].reason.oneOf.0","typeLabel":"string"},{"type":"null","description":"The free text whoever asked for the refund supplied, or null.\nYour own words when you sent them; it is never an enum.\n","isRequired":true,"uniqueKey":"oneOf.1.data.refunds.items.[INDEX].reason.oneOf.1","typeLabel":"null"}],"isRequired":true,"uniqueKey":"oneOf.1.data.refunds.items.[INDEX].reason","typeLabel":"string | null"},"status":{"type":"string","enum":["pending","succeeded","failed"],"description":"`pending` IS NOT A FAILURE and must not be retried: a\ndirect-charge refund is held while the account's balance is\nshort and applied once funds land. It flips to `succeeded` on\nits own and publishes that as `delivery.updated`. `failed`\nmeans nothing moved.\n","isRequired":true,"uniqueKey":"oneOf.1.data.refunds.items.[INDEX].status","typeLabel":"enum\u003cstring>"},"requested_via":{"type":"string","enum":["api","console","automatic","external"],"description":"Which lane issued it. `api` is your own\n`POST /v1/deliveries/{id}/refunds`. `console` is the merchant\npressing it in the Listo console. `automatic` is one we issued\nwith nobody asking, on a cancel or a return. `external` is one\nmade in the merchant's own payment dashboard, which we learned\nabout afterwards.\n","isRequired":true,"uniqueKey":"oneOf.1.data.refunds.items.[INDEX].requested_via","typeLabel":"enum\u003cstring>"},"party":{"type":"string","enum":["business","platform"],"description":"Whose decision it was. `business` is the merchant, or you\nacting for your store. `platform` is Listo issuing it because\nthe order ended without reaching the customer.\n","isRequired":true,"uniqueKey":"oneOf.1.data.refunds.items.[INDEX].party","typeLabel":"enum\u003cstring>"},"created_at":{"type":"string","format":"date-time","description":"When the refund was asked for.","isRequired":true,"uniqueKey":"oneOf.1.data.refunds.items.[INDEX].created_at","typeLabel":"string\u003cdate-time>"},"succeeded_at":{"oneOf":[{"type":"string","format":"date-time","description":"When the money was confirmed on its way. Null on a pending or\nfailed refund.\n","isRequired":true,"uniqueKey":"oneOf.1.data.refunds.items.[INDEX].succeeded_at.oneOf.0","typeLabel":"string\u003cdate-time>"},{"type":"null","format":"date-time","description":"When the money was confirmed on its way. Null on a pending or\nfailed refund.\n","isRequired":true,"uniqueKey":"oneOf.1.data.refunds.items.[INDEX].succeeded_at.oneOf.1","typeLabel":"null"}],"isRequired":true,"uniqueKey":"oneOf.1.data.refunds.items.[INDEX].succeeded_at","typeLabel":"string\u003cdate-time> | null"}},"required":["id","amount_cents","reason","status","requested_via","party","created_at","succeeded_at"],"uniqueKey":"oneOf.1.data.refunds.items.[INDEX]","typeLabel":"object"},"isRequired":true,"uniqueKey":"oneOf.1.data.refunds","typeLabel":"object[]"},"refunded_cents":{"type":"integer","description":"The sum of the SUCCEEDED refunds above, in Mexican peso cents. 0,\nnever null, on an order nothing has gone back on. A `pending` refund\nis not counted, because the money has not moved and may yet be\nrefused.\n\nPublished rather than left for you to compute, because the array\ncannot always be summed correctly: a refund of the remaining balance\ncarries no `amount_cents` until it is confirmed, so adding the\nlist up counts it as zero and reads the whole charge as still\nrefundable. We take that case pessimistically instead, as having\ntaken the entire remaining balance, because guessing low ends in\nrefunding a customer twice.\n","isRequired":true,"uniqueKey":"oneOf.1.data.refunded_cents","typeLabel":"integer"},"refundable_cents":{"type":"integer","description":"What a further refund could still return: what the customer paid\n(`order_value_cents` plus `customer_fee_cents`, which IS the charge)\nminus `refunded_cents`, floored at zero. 0, never null.\n\n0 on any order with no collected card payment behind it, whatever\nits value. Cash never touched our rails, a prepaid order's customer\nis yours and we hold nothing of theirs, and an order still awaiting\npayment was never charged, so there is nothing on any of them a\nrefund could return.\n\nThis is the ceiling `POST /v1/deliveries/{id}/refunds` refuses an\n`amount_cents` against, so read it before you call rather than\ndiscovering the bound from a `refund_amount_too_large`.\n","isRequired":true,"uniqueKey":"oneOf.1.data.refundable_cents","typeLabel":"integer"},"support_reference":{"oneOf":[{"type":"string","description":"A short handle to quote when you escalate an order to us. Null until\nthe order reaches dispatch.\n","example":"2080F","isRequired":true,"uniqueKey":"oneOf.1.data.support_reference.oneOf.0","typeLabel":"string"},{"type":"null","description":"A short handle to quote when you escalate an order to us. Null until\nthe order reaches dispatch.\n","example":"2080F","isRequired":true,"uniqueKey":"oneOf.1.data.support_reference.oneOf.1","typeLabel":"null"}],"isRequired":true,"uniqueKey":"oneOf.1.data.support_reference","typeLabel":"string | null"},"pickup_ready_at":{"oneOf":[{"type":"string","format":"date-time","description":"The scheduled pickup time you asked for. Null on a dispatch-now order.","isRequired":true,"uniqueKey":"oneOf.1.data.pickup_ready_at.oneOf.0","typeLabel":"string\u003cdate-time>"},{"type":"null","format":"date-time","description":"The scheduled pickup time you asked for. Null on a dispatch-now order.","isRequired":true,"uniqueKey":"oneOf.1.data.pickup_ready_at.oneOf.1","typeLabel":"null"}],"isRequired":true,"uniqueKey":"oneOf.1.data.pickup_ready_at","typeLabel":"string\u003cdate-time> | null"},"requested_at":{"oneOf":[{"type":"string","format":"date-time","isRequired":true,"uniqueKey":"oneOf.1.data.requested_at.oneOf.0","typeLabel":"string\u003cdate-time>"},{"type":"null","format":"date-time","isRequired":true,"uniqueKey":"oneOf.1.data.requested_at.oneOf.1","typeLabel":"null"}],"isRequired":true,"uniqueKey":"oneOf.1.data.requested_at","typeLabel":"string\u003cdate-time> | null"},"courier_assigned_at":{"oneOf":[{"type":"string","format":"date-time","description":"When a courier was first observed on the current attempt. Honestly\nan observation rather than an assignment clock, because no\nassignment time is published to us. Null on an attempt that never\nhad one.\n","isRequired":true,"uniqueKey":"oneOf.1.data.courier_assigned_at.oneOf.0","typeLabel":"string\u003cdate-time>"},{"type":"null","format":"date-time","description":"When a courier was first observed on the current attempt. Honestly\nan observation rather than an assignment clock, because no\nassignment time is published to us. Null on an attempt that never\nhad one.\n","isRequired":true,"uniqueKey":"oneOf.1.data.courier_assigned_at.oneOf.1","typeLabel":"null"}],"isRequired":true,"uniqueKey":"oneOf.1.data.courier_assigned_at","typeLabel":"string\u003cdate-time> | null"},"picked_up_at":{"oneOf":[{"type":"string","format":"date-time","isRequired":true,"uniqueKey":"oneOf.1.data.picked_up_at.oneOf.0","typeLabel":"string\u003cdate-time>"},{"type":"null","format":"date-time","isRequired":true,"uniqueKey":"oneOf.1.data.picked_up_at.oneOf.1","typeLabel":"null"}],"isRequired":true,"uniqueKey":"oneOf.1.data.picked_up_at","typeLabel":"string\u003cdate-time> | null"},"delivered_at":{"oneOf":[{"type":"string","format":"date-time","isRequired":true,"uniqueKey":"oneOf.1.data.delivered_at.oneOf.0","typeLabel":"string\u003cdate-time>"},{"type":"null","format":"date-time","isRequired":true,"uniqueKey":"oneOf.1.data.delivered_at.oneOf.1","typeLabel":"null"}],"isRequired":true,"uniqueKey":"oneOf.1.data.delivered_at","typeLabel":"string\u003cdate-time> | null"},"canceled_at":{"oneOf":[{"type":"string","format":"date-time","isRequired":true,"uniqueKey":"oneOf.1.data.canceled_at.oneOf.0","typeLabel":"string\u003cdate-time>"},{"type":"null","format":"date-time","isRequired":true,"uniqueKey":"oneOf.1.data.canceled_at.oneOf.1","typeLabel":"null"}],"isRequired":true,"uniqueKey":"oneOf.1.data.canceled_at","typeLabel":"string\u003cdate-time> | null"},"returned_at":{"oneOf":[{"type":"string","format":"date-time","isRequired":true,"uniqueKey":"oneOf.1.data.returned_at.oneOf.0","typeLabel":"string\u003cdate-time>"},{"type":"null","format":"date-time","isRequired":true,"uniqueKey":"oneOf.1.data.returned_at.oneOf.1","typeLabel":"null"}],"isRequired":true,"uniqueKey":"oneOf.1.data.returned_at","typeLabel":"string\u003cdate-time> | null"},"created_at":{"type":"string","format":"date-time","isRequired":true,"uniqueKey":"oneOf.1.data.created_at","typeLabel":"string\u003cdate-time>"},"updated_at":{"type":"string","format":"date-time","isRequired":true,"uniqueKey":"oneOf.1.data.updated_at","typeLabel":"string\u003cdate-time>"}},"required":["id","external_id","origin","code","status","store_id","test","payment","order_value_cents","fee_cents","business_fee_cents","customer_fee_cents","tip_cents","currency","quote_id","pickup","dropoff","manifest","vehicle","courier","pickup_eta_at","dropoff_eta_at","tracking_url","verification","return_verification","proof","proofs","cancellation","failure_reason","support_reference","pickup_ready_at","requested_at","courier_assigned_at","picked_up_at","delivered_at","canceled_at","returned_at","created_at","updated_at","charges","refunds","refunded_cents","refundable_cents"],"isRequired":true,"uniqueKey":"oneOf.1.data","typeLabel":"object"},"test":{"type":"boolean","description":"Present, and true, only on a test event you asked for with\n`POST /v1/test_webhooks`. A real event does not carry the field at\nall. A test event's `data` is a sample whose ids resolve to nothing.\n","example":true,"uniqueKey":"oneOf.1.test","typeLabel":"boolean"}},"uniqueKey":"oneOf.1","typeLabel":"object"},{"type":"object","description":"Every event your webhook endpoint receives, and every event the\ndebugging reads return: one of the six below, told apart by `type`.\n`data` is the object the event is about, and its shape depends on\n`type`. See `WebhookEventEnvelope` for the fields they all share and for\nhow delivery behaves (at-least-once, unordered).\n","required":["type","data","id","created_at"],"properties":{"id":{"type":"string","description":"The event id, `evt_` prefixed. Dedupe on this.","example":"evt_9pQ2vX7mKdR4tYb1nZ3sLwCe","isRequired":true,"uniqueKey":"oneOf.2.id","typeLabel":"string"},"created_at":{"type":"string","format":"date-time","description":"When the event was recorded, ISO-8601 in UTC.","example":"2026-07-28T18:41:03Z","isRequired":true,"uniqueKey":"oneOf.2.created_at","typeLabel":"string\u003cdate-time>"},"type":{"type":"string","description":"Which event this is.","enum":["delivery.courier_location"],"isRequired":true,"uniqueKey":"oneOf.2.type","typeLabel":"enum\u003cstring>"},"data":{"type":"object","description":"The reduced body of a `delivery.courier_location` event. Correlate it\nwith a delivery you already hold; it is not the delivery object.\n","properties":{"delivery_id":{"type":"string","description":"The `dlv_` id of the delivery the courier is carrying.","isRequired":true,"uniqueKey":"oneOf.2.data.delivery_id","typeLabel":"string"},"external_id":{"oneOf":[{"type":"string","description":"Your own reference for that delivery, so you need not store ours.","isRequired":true,"uniqueKey":"oneOf.2.data.external_id.oneOf.0","typeLabel":"string"},{"type":"null","description":"Your own reference for that delivery, so you need not store ours.","isRequired":true,"uniqueKey":"oneOf.2.data.external_id.oneOf.1","typeLabel":"null"}],"isRequired":true,"uniqueKey":"oneOf.2.data.external_id","typeLabel":"string | null"},"location":{"type":"object","properties":{"lat":{"type":"number","format":"double","isRequired":true,"uniqueKey":"oneOf.2.data.location.lat","typeLabel":"number\u003cdouble>"},"lng":{"type":"number","format":"double","isRequired":true,"uniqueKey":"oneOf.2.data.location.lng","typeLabel":"number\u003cdouble>"}},"required":["lat","lng"],"isRequired":true,"uniqueKey":"oneOf.2.data.location","typeLabel":"object"},"updated_at":{"oneOf":[{"type":"string","format":"date-time","description":"When this position was last confirmed, which is not the same as when\nthe event was sent.\n","isRequired":true,"uniqueKey":"oneOf.2.data.updated_at.oneOf.0","typeLabel":"string\u003cdate-time>"},{"type":"null","format":"date-time","description":"When this position was last confirmed, which is not the same as when\nthe event was sent.\n","isRequired":true,"uniqueKey":"oneOf.2.data.updated_at.oneOf.1","typeLabel":"null"}],"isRequired":true,"uniqueKey":"oneOf.2.data.updated_at","typeLabel":"string\u003cdate-time> | null"}},"required":["delivery_id","external_id","location","updated_at"],"isRequired":true,"uniqueKey":"oneOf.2.data","typeLabel":"object"},"test":{"type":"boolean","description":"Present, and true, only on a test event you asked for with\n`POST /v1/test_webhooks`. A real event does not carry the field at\nall. A test event's `data` is a sample whose ids resolve to nothing.\n","example":true,"uniqueKey":"oneOf.2.test","typeLabel":"boolean"}},"uniqueKey":"oneOf.2","typeLabel":"object"},{"type":"object","description":"Every event your webhook endpoint receives, and every event the\ndebugging reads return: one of the six below, told apart by `type`.\n`data` is the object the event is about, and its shape depends on\n`type`. See `WebhookEventEnvelope` for the fields they all share and for\nhow delivery behaves (at-least-once, unordered).\n","required":["type","data","id","created_at"],"properties":{"id":{"type":"string","description":"The event id, `evt_` prefixed. Dedupe on this.","example":"evt_9pQ2vX7mKdR4tYb1nZ3sLwCe","isRequired":true,"uniqueKey":"oneOf.3.id","typeLabel":"string"},"created_at":{"type":"string","format":"date-time","description":"When the event was recorded, ISO-8601 in UTC.","example":"2026-07-28T18:41:03Z","isRequired":true,"uniqueKey":"oneOf.3.created_at","typeLabel":"string\u003cdate-time>"},"type":{"type":"string","description":"Which event this is.","enum":["withdrawal.updated"],"isRequired":true,"uniqueKey":"oneOf.3.type","typeLabel":"enum\u003cstring>"},"data":{"type":"object","description":"A request to move money out of your balance to your bank account.","properties":{"id":{"type":"string","description":"The withdrawal id, `wd_` prefixed.","example":"wd_2xN6bK9mR4tQ7vC1sZ8pLwYe","isRequired":true,"uniqueKey":"oneOf.3.data.id","typeLabel":"string"},"amount_cents":{"type":"integer","description":"What your bank receives. On a `same_day` withdrawal the fee is a\nSECOND debit rather than a deduction, so this figure is what lands\neither way and `fee_cents` is what your balance loses on top of it.\n","isRequired":true,"uniqueKey":"oneOf.3.data.amount_cents","typeLabel":"integer"},"fee_cents":{"type":"integer","description":"What the withdrawal cost, IVA included. Always `0` on a `standard`\nwithdrawal. Always present.\n","isRequired":true,"uniqueKey":"oneOf.3.data.fee_cents","typeLabel":"integer"},"currency":{"type":"string","enum":["MXN"],"isRequired":true,"uniqueKey":"oneOf.3.data.currency","typeLabel":"enum\u003cstring>"},"kind":{"type":"string","enum":["standard","same_day"],"description":"`standard` is the free path: your released balance only, sent in 1\nto 3 business days. `same_day` costs `fee_cents`, can reach cash\nstill on hold, and is sent the same day within the hours in\n`POST /v1/withdrawals`.\n","isRequired":true,"uniqueKey":"oneOf.3.data.kind","typeLabel":"enum\u003cstring>"},"status":{"type":"string","enum":["pending","paid","failed"],"description":"`pending` until a human settles it. The move to `paid` or `failed`\nis what `withdrawal.updated` announces.\n","isRequired":true,"uniqueKey":"oneOf.3.data.status","typeLabel":"enum\u003cstring>"},"requested_at":{"oneOf":[{"type":"string","format":"date-time","isRequired":true,"uniqueKey":"oneOf.3.data.requested_at.oneOf.0","typeLabel":"string\u003cdate-time>"},{"type":"null","format":"date-time","isRequired":true,"uniqueKey":"oneOf.3.data.requested_at.oneOf.1","typeLabel":"null"}],"isRequired":true,"uniqueKey":"oneOf.3.data.requested_at","typeLabel":"string\u003cdate-time> | null"},"due_at":{"oneOf":[{"type":"string","format":"date-time","description":"When a `same_day` withdrawal is due to have been sent, stamped when\nyou requested it and never recalculated afterwards. Null on every\n`standard` withdrawal: the free path promises a range of business\ndays rather than an instant.\n","isRequired":true,"uniqueKey":"oneOf.3.data.due_at.oneOf.0","typeLabel":"string\u003cdate-time>"},{"type":"null","format":"date-time","description":"When a `same_day` withdrawal is due to have been sent, stamped when\nyou requested it and never recalculated afterwards. Null on every\n`standard` withdrawal: the free path promises a range of business\ndays rather than an instant.\n","isRequired":true,"uniqueKey":"oneOf.3.data.due_at.oneOf.1","typeLabel":"null"}],"isRequired":true,"uniqueKey":"oneOf.3.data.due_at","typeLabel":"string\u003cdate-time> | null"},"resolved_at":{"oneOf":[{"type":"string","format":"date-time","description":"Null while still pending.","isRequired":true,"uniqueKey":"oneOf.3.data.resolved_at.oneOf.0","typeLabel":"string\u003cdate-time>"},{"type":"null","format":"date-time","description":"Null while still pending.","isRequired":true,"uniqueKey":"oneOf.3.data.resolved_at.oneOf.1","typeLabel":"null"}],"isRequired":true,"uniqueKey":"oneOf.3.data.resolved_at","typeLabel":"string\u003cdate-time> | null"},"clave_de_rastreo":{"oneOf":[{"type":["string","null"],"description":"The SPEI tracking key for the transfer: the identifier your own bank\nuses to locate the deposit. This is what you reconcile a payout\nagainst a bank statement with, and it is the same key you see in the\ndashboard for this withdrawal.\n\nAlways present, null until the transfer is sent. It stays null\nforever on a `failed` withdrawal, because no transfer happened.\n","example":"MBAN01002608120001234567","isRequired":true,"uniqueKey":"oneOf.3.data.clave_de_rastreo.oneOf.0","typeLabel":"string"},{"type":"null","description":"The SPEI tracking key for the transfer: the identifier your own bank\nuses to locate the deposit. This is what you reconcile a payout\nagainst a bank statement with, and it is the same key you see in the\ndashboard for this withdrawal.\n\nAlways present, null until the transfer is sent. It stays null\nforever on a `failed` withdrawal, because no transfer happened.\n","example":"MBAN01002608120001234567","isRequired":true,"uniqueKey":"oneOf.3.data.clave_de_rastreo.oneOf.1","typeLabel":"null"}],"isRequired":true,"uniqueKey":"oneOf.3.data.clave_de_rastreo","typeLabel":"string | null"},"test":{"type":"boolean","isRequired":true,"uniqueKey":"oneOf.3.data.test","typeLabel":"boolean"}},"required":["id","amount_cents","fee_cents","currency","kind","status","requested_at","due_at","resolved_at","clave_de_rastreo","test"],"isRequired":true,"uniqueKey":"oneOf.3.data","typeLabel":"object"},"test":{"type":"boolean","description":"Present, and true, only on a test event you asked for with\n`POST /v1/test_webhooks`. A real event does not carry the field at\nall. A test event's `data` is a sample whose ids resolve to nothing.\n","example":true,"uniqueKey":"oneOf.3.test","typeLabel":"boolean"}},"uniqueKey":"oneOf.3","typeLabel":"object"},{"type":"object","description":"Every event your webhook endpoint receives, and every event the\ndebugging reads return: one of the six below, told apart by `type`.\n`data` is the object the event is about, and its shape depends on\n`type`. See `WebhookEventEnvelope` for the fields they all share and for\nhow delivery behaves (at-least-once, unordered).\n","required":["type","data","id","created_at"],"properties":{"id":{"type":"string","description":"The event id, `evt_` prefixed. Dedupe on this.","example":"evt_9pQ2vX7mKdR4tYb1nZ3sLwCe","isRequired":true,"uniqueKey":"oneOf.4.id","typeLabel":"string"},"created_at":{"type":"string","format":"date-time","description":"When the event was recorded, ISO-8601 in UTC.","example":"2026-07-28T18:41:03Z","isRequired":true,"uniqueKey":"oneOf.4.created_at","typeLabel":"string\u003cdate-time>"},"type":{"type":"string","description":"Which event this is.","enum":["store.updated"],"isRequired":true,"uniqueKey":"oneOf.4.type","typeLabel":"enum\u003cstring>"},"data":{"type":"object","description":"A pickup location. Card readiness is deliberately NOT a field here: it\nis its own endpoint, with its own outstanding-requirements detail.\n","properties":{"id":{"type":"string","description":"The store id, `st_` prefixed.","example":"st_4bR8kM2wQ7xT1nV5cZ9pLdYe","isRequired":true,"uniqueKey":"oneOf.4.data.id","typeLabel":"string"},"external_id":{"oneOf":[{"type":"string","description":"Your own reference for this location, if you sent one. Unique per\nkey world, and filterable on the list, so you can reconcile against\nyour own store book without storing our ids.\n","example":"pos-store-41","isRequired":true,"uniqueKey":"oneOf.4.data.external_id.oneOf.0","typeLabel":"string"},{"type":"null","description":"Your own reference for this location, if you sent one. Unique per\nkey world, and filterable on the list, so you can reconcile against\nyour own store book without storing our ids.\n","example":"pos-store-41","isRequired":true,"uniqueKey":"oneOf.4.data.external_id.oneOf.1","typeLabel":"null"}],"isRequired":true,"uniqueKey":"oneOf.4.data.external_id","typeLabel":"string | null"},"name":{"type":"string","description":"The name you gave the store; for a restaurant that connected an\naccount with several branches, the business and the branch, the way\nits own customers read it (`Tortería La Mera Mera, Zapopan`). A\nbranch whose own name already begins with the business's name, such\nas `Tortería La Mera Mera Centro`, is published as it is. When\nyou send a name, a value that begins with the store's business name\nand a comma is read as that business plus the branch, so sending back\nthe name you read changes nothing.\n","isRequired":true,"uniqueKey":"oneOf.4.data.name","typeLabel":"string"},"phone":{"type":"string","description":"E.164, normalized on the way in.","isRequired":true,"uniqueKey":"oneOf.4.data.phone","typeLabel":"string"},"street":{"type":"string","isRequired":true,"uniqueKey":"oneOf.4.data.street","typeLabel":"string"},"apt_unit":{"oneOf":[{"type":"string","isRequired":true,"uniqueKey":"oneOf.4.data.apt_unit.oneOf.0","typeLabel":"string"},{"type":"null","isRequired":true,"uniqueKey":"oneOf.4.data.apt_unit.oneOf.1","typeLabel":"null"}],"isRequired":true,"uniqueKey":"oneOf.4.data.apt_unit","typeLabel":"string | null"},"lat":{"oneOf":[{"type":"number","format":"double","isRequired":true,"uniqueKey":"oneOf.4.data.lat.oneOf.0","typeLabel":"number\u003cdouble>"},{"type":"null","format":"double","isRequired":true,"uniqueKey":"oneOf.4.data.lat.oneOf.1","typeLabel":"null"}],"isRequired":true,"uniqueKey":"oneOf.4.data.lat","typeLabel":"number\u003cdouble> | null"},"lng":{"oneOf":[{"type":"number","format":"double","isRequired":true,"uniqueKey":"oneOf.4.data.lng.oneOf.0","typeLabel":"number\u003cdouble>"},{"type":"null","format":"double","isRequired":true,"uniqueKey":"oneOf.4.data.lng.oneOf.1","typeLabel":"null"}],"isRequired":true,"uniqueKey":"oneOf.4.data.lng","typeLabel":"number\u003cdouble> | null"},"pickup_notes":{"oneOf":[{"type":"string","description":"Standing instructions for the courier collecting here.","isRequired":true,"uniqueKey":"oneOf.4.data.pickup_notes.oneOf.0","typeLabel":"string"},{"type":"null","description":"Standing instructions for the courier collecting here.","isRequired":true,"uniqueKey":"oneOf.4.data.pickup_notes.oneOf.1","typeLabel":"null"}],"isRequired":true,"uniqueKey":"oneOf.4.data.pickup_notes","typeLabel":"string | null"},"timezone":{"type":"string","description":"The IANA zone the store keeps its hours in, normalized to one\nspelling per zone. Derived from the store's coordinates, and\nre-derived whenever the store's position moves. A zone you send\nyourself is used only when the position cannot answer (a store with\nno coordinates, or a position no zone claims), and one that\ndisagrees with the position is neither stored nor treated as an\nerror.\n","example":"America/Mexico_City","isRequired":true,"uniqueKey":"oneOf.4.data.timezone","typeLabel":"string"},"default_business_fee_share":{"type":"integer","minimum":0,"maximum":100,"description":"The share of the delivery fee this store covers by default, as a\npercentage. The rest is charged to the customer. In force only when\n`default_fee_split_mode` is `percent`; in either amount mode this is\nthe percentage the store keeps for when it goes back to one.\n","isRequired":true,"uniqueKey":"oneOf.4.data.default_business_fee_share","typeLabel":"integer"},"default_fee_split_mode":{"type":"string","enum":["percent","business_amount","customer_amount"],"description":"Which shape this store's default split has, and therefore which of\nthe two fields above and below is in force. `percent` splits the fee\nby `default_business_fee_share`; `business_amount` means the store\ncovers up to `default_fee_split_amount_cents` of it and the customer\npays the rest; `customer_amount` is the mirror, the customer paying\nup to that amount and the store covering the rest.\n\nRead-only. It is set by the restaurant in its own Listo console, and\nsending `default_business_fee_share` on a create or an update moves\nthe store back to `percent`.\n","isRequired":true,"uniqueKey":"oneOf.4.data.default_fee_split_mode","typeLabel":"enum\u003cstring>"},"default_fee_split_amount_cents":{"oneOf":[{"type":"integer","minimum":0,"description":"The amount the two amount modes divide the fee by, in cents. Null in\n`percent` mode, and never null in either amount mode. Read-only.\n","isRequired":true,"uniqueKey":"oneOf.4.data.default_fee_split_amount_cents.oneOf.0","typeLabel":"integer"},{"type":"null","minimum":0,"description":"The amount the two amount modes divide the fee by, in cents. Null in\n`percent` mode, and never null in either amount mode. Read-only.\n","isRequired":true,"uniqueKey":"oneOf.4.data.default_fee_split_amount_cents.oneOf.1","typeLabel":"null"}],"isRequired":true,"uniqueKey":"oneOf.4.data.default_fee_split_amount_cents","typeLabel":"integer | null"},"access_tier":{"type":"string","enum":["api_only","wallet","full"],"description":"How much of Listo the store itself uses. An `api_only` store's\ndeliveries spend your balance, and a `wallet` or `full` store's\nspend its own; `billing` says which. Writable on create and update,\nand always `api_only` on a test store. A live store of an account\nwhose restaurants pay their own Plan Listo cannot be `api_only`: it\nhas no console to buy a plan from, so a create or an update that\nasks for it is refused with `422 validation_failed` and\n`param: \"access_tier\"`.\n","isRequired":true,"uniqueKey":"oneOf.4.data.access_tier","typeLabel":"enum\u003cstring>"},"markup_cents":{"type":"integer","minimum":0,"description":"Your own markup on every delivery of this store, in cents. It is\nadded to the delivery fee, split with the customer like the rest of\nthe fee, and credited to your balance when the delivery is\ndelivered. Writable on create and update.\n","isRequired":true,"uniqueKey":"oneOf.4.data.markup_cents","typeLabel":"integer"},"billing":{"type":"string","enum":["partner","store"],"description":"Whose balance pays this store's deliveries, read off `access_tier`\nso you never have to derive it: `partner` is yours, `store` is the\nstore's own. Read-only. It is not who pays the store's plan, which\nis `plan.paid_by`.\n","isRequired":true,"uniqueKey":"oneOf.4.data.billing","typeLabel":"enum\u003cstring>"},"test":{"type":"boolean","isRequired":true,"uniqueKey":"oneOf.4.data.test","typeLabel":"boolean"},"created_at":{"type":"string","format":"date-time","isRequired":true,"uniqueKey":"oneOf.4.data.created_at","typeLabel":"string\u003cdate-time>"},"plan":{"oneOf":[{"description":"The store's Plan Listo, or `null` when the store needs no plan: a\ntest store, or a live store created before Plan Listo existed, which\nkeeps requesting couriers without one. It is also `null` when the\nstore pays its own plan (every store of an account whose stores pay\ntheir own Plan Listo) and the restaurant has not bought one yet: the\nrestaurant buys it in its own console, and there is nothing for you\nto pay or to reactivate. It is also `null` for a store of a partner\non pricing with no Plan Listo, which needs no plan. When it is an\nobject every\nkey is present, and the ones that do not apply are `null`. See\n[Plan and billing](https://docs.listo.delivery/en/guides/plan-and-billing).\n","type":"object","properties":{"status":{"type":"string","enum":["active","past_due","canceling","canceled","awaiting_payment"],"description":"`active` is paid up and renews on `next_charge_on` (null on a\nplan that is passing to the restaurant, see `pending_paid_by`). `past_due`\nhas an unpaid month, and its deliveries are refused with `402\nplan_required` until the charge goes through. `awaiting_payment`\nis a store whose first month your balance and card could not\ncover: it holds no plan yet, `price_cents` is the price it\nwill be charged before IVA (the amount needed to pay is that\nplus IVA), every date is null, its deliveries are refused with\n`402 plan_required`, and Listo charges it by itself as soon as\nyour balance or card covers it. `canceling` was\ncanceled and is served up to the day before `ends_on`.\n`canceled` has ended, and can be restarted.\n","isRequired":true,"uniqueKey":"oneOf.4.data.plan.oneOf.0.status","typeLabel":"enum\u003cstring>"},"price_cents":{"type":"integer","description":"What one month of this store's plan costs you, before IVA: your\nprice, even while a restaurant that connected to you is still\npaying its own plan. When `paid_by` is `store` because the\nstore pays its own plan, it is the price of one `interval` of\nthe restaurant's own plan, which is not yours to pay.\n","example":199000,"isRequired":true,"uniqueKey":"oneOf.4.data.plan.oneOf.0.price_cents","typeLabel":"integer"},"currency":{"type":"string","example":"MXN","isRequired":true,"uniqueKey":"oneOf.4.data.plan.oneOf.0.currency","typeLabel":"string"},"interval":{"type":"string","description":"How long one period of this plan is, and the cycle `price_cents`\nis the price of. `month` for every plan you pay. A store that\npays its own plan reports the interval its restaurant bought,\nso `year` is a restaurant that paid twelve months at once.\n","example":"month","isRequired":true,"uniqueKey":"oneOf.4.data.plan.oneOf.0.interval","typeLabel":"string"},"current_period_ends_on":{"oneOf":[{"type":"string","format":"date","description":"The last day of the current period, already paid unless\n`status` is `past_due`.\n","isRequired":true,"uniqueKey":"oneOf.4.data.plan.oneOf.0.current_period_ends_on.oneOf.0","typeLabel":"string\u003cdate>"},{"type":"null","format":"date","description":"The last day of the current period, already paid unless\n`status` is `past_due`.\n","isRequired":true,"uniqueKey":"oneOf.4.data.plan.oneOf.0.current_period_ends_on.oneOf.1","typeLabel":"null"}],"isRequired":true,"uniqueKey":"oneOf.4.data.plan.oneOf.0.current_period_ends_on","typeLabel":"string\u003cdate> | null"},"next_charge_on":{"oneOf":[{"type":"string","format":"date","description":"The day you are charged next: the next renewal, or, while a\nrestaurant that connected to you still pays its own plan, your\nfirst charge. Null once the plan is ending or has ended, and\nnull while it is `past_due`: the month owed is charged the\nmoment your balance or saved card allows, and retried every\nday until it is paid. Null while `courtesy` is true, too. Null\nas well on a plan you pay that is passing to the restaurant\n(`pending_paid_by` is `store`): you pay the period you are in\nand nothing after it. When `paid_by` is `store` because the\nstore pays its own plan, it is the day the restaurant's own plan\nrenews, not a charge to you.\n","isRequired":true,"uniqueKey":"oneOf.4.data.plan.oneOf.0.next_charge_on.oneOf.0","typeLabel":"string\u003cdate>"},{"type":"null","format":"date","description":"The day you are charged next: the next renewal, or, while a\nrestaurant that connected to you still pays its own plan, your\nfirst charge. Null once the plan is ending or has ended, and\nnull while it is `past_due`: the month owed is charged the\nmoment your balance or saved card allows, and retried every\nday until it is paid. Null while `courtesy` is true, too. Null\nas well on a plan you pay that is passing to the restaurant\n(`pending_paid_by` is `store`): you pay the period you are in\nand nothing after it. When `paid_by` is `store` because the\nstore pays its own plan, it is the day the restaurant's own plan\nrenews, not a charge to you.\n","isRequired":true,"uniqueKey":"oneOf.4.data.plan.oneOf.0.next_charge_on.oneOf.1","typeLabel":"null"}],"isRequired":true,"uniqueKey":"oneOf.4.data.plan.oneOf.0.next_charge_on","typeLabel":"string\u003cdate> | null"},"canceled_at":{"oneOf":[{"type":"string","format":"date-time","description":"When you canceled the plan.","isRequired":true,"uniqueKey":"oneOf.4.data.plan.oneOf.0.canceled_at.oneOf.0","typeLabel":"string\u003cdate-time>"},{"type":"null","format":"date-time","description":"When you canceled the plan.","isRequired":true,"uniqueKey":"oneOf.4.data.plan.oneOf.0.canceled_at.oneOf.1","typeLabel":"null"}],"isRequired":true,"uniqueKey":"oneOf.4.data.plan.oneOf.0.canceled_at","typeLabel":"string\u003cdate-time> | null"},"ends_on":{"oneOf":[{"type":"string","format":"date","description":"The day the plan stops serving the store, which is the day after\nthe last day paid, or the day a plan whose charge was pending was\ncanceled. Null unless the plan is ending or has ended.\n","isRequired":true,"uniqueKey":"oneOf.4.data.plan.oneOf.0.ends_on.oneOf.0","typeLabel":"string\u003cdate>"},{"type":"null","format":"date","description":"The day the plan stops serving the store, which is the day after\nthe last day paid, or the day a plan whose charge was pending was\ncanceled. Null unless the plan is ending or has ended.\n","isRequired":true,"uniqueKey":"oneOf.4.data.plan.oneOf.0.ends_on.oneOf.1","typeLabel":"null"}],"isRequired":true,"uniqueKey":"oneOf.4.data.plan.oneOf.0.ends_on","typeLabel":"string\u003cdate> | null"},"paid_by":{"type":"string","enum":["partner","store"],"description":"Who pays this plan: `partner`, which is you, or `store`, the\nrestaurant itself. `store` is a restaurant that connected to you\nand still pays its own plan, and every store that pays its own\nPlan Listo because your account is set up that way; none of\nthose is yours to pay.\n","isRequired":true,"uniqueKey":"oneOf.4.data.plan.oneOf.0.paid_by","typeLabel":"enum\u003cstring>"},"pending_paid_by":{"oneOf":[{"type":"string","description":"Who will pay it from `pending_paid_by_on`, when that is about to\nchange, or null. `partner` is you: a restaurant that connected to\nyou and still pays its own plan, until the renewal you pay from.\n`store` is the restaurant: a plan you pay that passes to the\nrestaurant at its next renewal because your account is set up so\nthat each restaurant pays its own plan. You pay the period you\nare in and nothing after it, so `next_charge_on` is null.\n","isRequired":true,"uniqueKey":"oneOf.4.data.plan.oneOf.0.pending_paid_by.oneOf.0","typeLabel":"string"},{"type":"null","description":"Who will pay it from `pending_paid_by_on`, when that is about to\nchange, or null. `partner` is you: a restaurant that connected to\nyou and still pays its own plan, until the renewal you pay from.\n`store` is the restaurant: a plan you pay that passes to the\nrestaurant at its next renewal because your account is set up so\nthat each restaurant pays its own plan. You pay the period you\nare in and nothing after it, so `next_charge_on` is null.\n","isRequired":true,"uniqueKey":"oneOf.4.data.plan.oneOf.0.pending_paid_by.oneOf.1","typeLabel":"null"}],"isRequired":true,"uniqueKey":"oneOf.4.data.plan.oneOf.0.pending_paid_by","typeLabel":"string | null"},"pending_paid_by_on":{"oneOf":[{"type":"string","format":"date","description":"The date that change lands (the day the new payer's first\nperiod starts), or null.\n","isRequired":true,"uniqueKey":"oneOf.4.data.plan.oneOf.0.pending_paid_by_on.oneOf.0","typeLabel":"string\u003cdate>"},{"type":"null","format":"date","description":"The date that change lands (the day the new payer's first\nperiod starts), or null.\n","isRequired":true,"uniqueKey":"oneOf.4.data.plan.oneOf.0.pending_paid_by_on.oneOf.1","typeLabel":"null"}],"isRequired":true,"uniqueKey":"oneOf.4.data.plan.oneOf.0.pending_paid_by_on","typeLabel":"string\u003cdate> | null"},"courtesy":{"type":"boolean","description":"`courtesy` is true while Listo waives this store's plan: nothing\nis charged and `next_charge_on` is null.\n","isRequired":true,"uniqueKey":"oneOf.4.data.plan.oneOf.0.courtesy","typeLabel":"boolean"}},"required":["status","price_cents","currency","interval","current_period_ends_on","next_charge_on","canceled_at","ends_on","paid_by","pending_paid_by","pending_paid_by_on","courtesy"],"isRequired":true,"uniqueKey":"oneOf.4.data.plan.oneOf.0","typeLabel":"object"},{"description":"The store's Plan Listo, or `null` when the store needs no plan: a\ntest store, or a live store created before Plan Listo existed, which\nkeeps requesting couriers without one. It is also `null` when the\nstore pays its own plan (every store of an account whose stores pay\ntheir own Plan Listo) and the restaurant has not bought one yet: the\nrestaurant buys it in its own console, and there is nothing for you\nto pay or to reactivate. It is also `null` for a store of a partner\non pricing with no Plan Listo, which needs no plan. When it is an\nobject every\nkey is present, and the ones that do not apply are `null`. See\n[Plan and billing](https://docs.listo.delivery/en/guides/plan-and-billing).\n","type":"null","properties":{"status":{"type":"string","enum":["active","past_due","canceling","canceled","awaiting_payment"],"description":"`active` is paid up and renews on `next_charge_on` (null on a\nplan that is passing to the restaurant, see `pending_paid_by`). `past_due`\nhas an unpaid month, and its deliveries are refused with `402\nplan_required` until the charge goes through. `awaiting_payment`\nis a store whose first month your balance and card could not\ncover: it holds no plan yet, `price_cents` is the price it\nwill be charged before IVA (the amount needed to pay is that\nplus IVA), every date is null, its deliveries are refused with\n`402 plan_required`, and Listo charges it by itself as soon as\nyour balance or card covers it. `canceling` was\ncanceled and is served up to the day before `ends_on`.\n`canceled` has ended, and can be restarted.\n"},"price_cents":{"type":"integer","description":"What one month of this store's plan costs you, before IVA: your\nprice, even while a restaurant that connected to you is still\npaying its own plan. When `paid_by` is `store` because the\nstore pays its own plan, it is the price of one `interval` of\nthe restaurant's own plan, which is not yours to pay.\n","example":199000},"currency":{"type":"string","example":"MXN"},"interval":{"type":"string","description":"How long one period of this plan is, and the cycle `price_cents`\nis the price of. `month` for every plan you pay. A store that\npays its own plan reports the interval its restaurant bought,\nso `year` is a restaurant that paid twelve months at once.\n","example":"month"},"current_period_ends_on":{"oneOf":[{"type":"string","format":"date","description":"The last day of the current period, already paid unless\n`status` is `past_due`.\n"},{"type":"null","format":"date","description":"The last day of the current period, already paid unless\n`status` is `past_due`.\n"}]},"next_charge_on":{"oneOf":[{"type":"string","format":"date","description":"The day you are charged next: the next renewal, or, while a\nrestaurant that connected to you still pays its own plan, your\nfirst charge. Null once the plan is ending or has ended, and\nnull while it is `past_due`: the month owed is charged the\nmoment your balance or saved card allows, and retried every\nday until it is paid. Null while `courtesy` is true, too. Null\nas well on a plan you pay that is passing to the restaurant\n(`pending_paid_by` is `store`): you pay the period you are in\nand nothing after it. When `paid_by` is `store` because the\nstore pays its own plan, it is the day the restaurant's own plan\nrenews, not a charge to you.\n"},{"type":"null","format":"date","description":"The day you are charged next: the next renewal, or, while a\nrestaurant that connected to you still pays its own plan, your\nfirst charge. Null once the plan is ending or has ended, and\nnull while it is `past_due`: the month owed is charged the\nmoment your balance or saved card allows, and retried every\nday until it is paid. Null while `courtesy` is true, too. Null\nas well on a plan you pay that is passing to the restaurant\n(`pending_paid_by` is `store`): you pay the period you are in\nand nothing after it. When `paid_by` is `store` because the\nstore pays its own plan, it is the day the restaurant's own plan\nrenews, not a charge to you.\n"}]},"canceled_at":{"oneOf":[{"type":"string","format":"date-time","description":"When you canceled the plan."},{"type":"null","format":"date-time","description":"When you canceled the plan."}]},"ends_on":{"oneOf":[{"type":"string","format":"date","description":"The day the plan stops serving the store, which is the day after\nthe last day paid, or the day a plan whose charge was pending was\ncanceled. Null unless the plan is ending or has ended.\n"},{"type":"null","format":"date","description":"The day the plan stops serving the store, which is the day after\nthe last day paid, or the day a plan whose charge was pending was\ncanceled. Null unless the plan is ending or has ended.\n"}]},"paid_by":{"type":"string","enum":["partner","store"],"description":"Who pays this plan: `partner`, which is you, or `store`, the\nrestaurant itself. `store` is a restaurant that connected to you\nand still pays its own plan, and every store that pays its own\nPlan Listo because your account is set up that way; none of\nthose is yours to pay.\n"},"pending_paid_by":{"oneOf":[{"type":"string","description":"Who will pay it from `pending_paid_by_on`, when that is about to\nchange, or null. `partner` is you: a restaurant that connected to\nyou and still pays its own plan, until the renewal you pay from.\n`store` is the restaurant: a plan you pay that passes to the\nrestaurant at its next renewal because your account is set up so\nthat each restaurant pays its own plan. You pay the period you\nare in and nothing after it, so `next_charge_on` is null.\n"},{"type":"null","description":"Who will pay it from `pending_paid_by_on`, when that is about to\nchange, or null. `partner` is you: a restaurant that connected to\nyou and still pays its own plan, until the renewal you pay from.\n`store` is the restaurant: a plan you pay that passes to the\nrestaurant at its next renewal because your account is set up so\nthat each restaurant pays its own plan. You pay the period you\nare in and nothing after it, so `next_charge_on` is null.\n"}]},"pending_paid_by_on":{"oneOf":[{"type":"string","format":"date","description":"The date that change lands (the day the new payer's first\nperiod starts), or null.\n"},{"type":"null","format":"date","description":"The date that change lands (the day the new payer's first\nperiod starts), or null.\n"}]},"courtesy":{"type":"boolean","description":"`courtesy` is true while Listo waives this store's plan: nothing\nis charged and `next_charge_on` is null.\n"}},"required":["status","price_cents","currency","interval","current_period_ends_on","next_charge_on","canceled_at","ends_on","paid_by","pending_paid_by","pending_paid_by_on","courtesy"],"isRequired":true,"uniqueKey":"oneOf.4.data.plan.oneOf.1","typeLabel":"null"}],"isRequired":true,"uniqueKey":"oneOf.4.data.plan","typeLabel":"object | null"}},"required":["id","external_id","name","phone","street","apt_unit","lat","lng","pickup_notes","timezone","default_business_fee_share","default_fee_split_mode","default_fee_split_amount_cents","access_tier","markup_cents","billing","test","created_at","plan"],"isRequired":true,"uniqueKey":"oneOf.4.data","typeLabel":"object"},"test":{"type":"boolean","description":"Present, and true, only on a test event you asked for with\n`POST /v1/test_webhooks`. A real event does not carry the field at\nall. A test event's `data` is a sample whose ids resolve to nothing.\n","example":true,"uniqueKey":"oneOf.4.test","typeLabel":"boolean"}},"uniqueKey":"oneOf.4","typeLabel":"object"},{"type":"object","description":"Every event your webhook endpoint receives, and every event the\ndebugging reads return: one of the six below, told apart by `type`.\n`data` is the object the event is about, and its shape depends on\n`type`. See `WebhookEventEnvelope` for the fields they all share and for\nhow delivery behaves (at-least-once, unordered).\n","required":["type","data","id","created_at"],"properties":{"id":{"type":"string","description":"The event id, `evt_` prefixed. Dedupe on this.","example":"evt_9pQ2vX7mKdR4tYb1nZ3sLwCe","isRequired":true,"uniqueKey":"oneOf.5.id","typeLabel":"string"},"created_at":{"type":"string","format":"date-time","description":"When the event was recorded, ISO-8601 in UTC.","example":"2026-07-28T18:41:03Z","isRequired":true,"uniqueKey":"oneOf.5.created_at","typeLabel":"string\u003cdate-time>"},"type":{"type":"string","description":"Which event this is.","enum":["store.connected"],"isRequired":true,"uniqueKey":"oneOf.5.type","typeLabel":"enum\u003cstring>"},"data":{"type":"object","description":"A pickup location. Card readiness is deliberately NOT a field here: it\nis its own endpoint, with its own outstanding-requirements detail.\n","properties":{"id":{"type":"string","description":"The store id, `st_` prefixed.","example":"st_4bR8kM2wQ7xT1nV5cZ9pLdYe","isRequired":true,"uniqueKey":"oneOf.5.data.id","typeLabel":"string"},"external_id":{"oneOf":[{"type":"string","description":"Your own reference for this location, if you sent one. Unique per\nkey world, and filterable on the list, so you can reconcile against\nyour own store book without storing our ids.\n","example":"pos-store-41","isRequired":true,"uniqueKey":"oneOf.5.data.external_id.oneOf.0","typeLabel":"string"},{"type":"null","description":"Your own reference for this location, if you sent one. Unique per\nkey world, and filterable on the list, so you can reconcile against\nyour own store book without storing our ids.\n","example":"pos-store-41","isRequired":true,"uniqueKey":"oneOf.5.data.external_id.oneOf.1","typeLabel":"null"}],"isRequired":true,"uniqueKey":"oneOf.5.data.external_id","typeLabel":"string | null"},"name":{"type":"string","description":"The name you gave the store; for a restaurant that connected an\naccount with several branches, the business and the branch, the way\nits own customers read it (`Tortería La Mera Mera, Zapopan`). A\nbranch whose own name already begins with the business's name, such\nas `Tortería La Mera Mera Centro`, is published as it is. When\nyou send a name, a value that begins with the store's business name\nand a comma is read as that business plus the branch, so sending back\nthe name you read changes nothing.\n","isRequired":true,"uniqueKey":"oneOf.5.data.name","typeLabel":"string"},"phone":{"type":"string","description":"E.164, normalized on the way in.","isRequired":true,"uniqueKey":"oneOf.5.data.phone","typeLabel":"string"},"street":{"type":"string","isRequired":true,"uniqueKey":"oneOf.5.data.street","typeLabel":"string"},"apt_unit":{"oneOf":[{"type":"string","isRequired":true,"uniqueKey":"oneOf.5.data.apt_unit.oneOf.0","typeLabel":"string"},{"type":"null","isRequired":true,"uniqueKey":"oneOf.5.data.apt_unit.oneOf.1","typeLabel":"null"}],"isRequired":true,"uniqueKey":"oneOf.5.data.apt_unit","typeLabel":"string | null"},"lat":{"oneOf":[{"type":"number","format":"double","isRequired":true,"uniqueKey":"oneOf.5.data.lat.oneOf.0","typeLabel":"number\u003cdouble>"},{"type":"null","format":"double","isRequired":true,"uniqueKey":"oneOf.5.data.lat.oneOf.1","typeLabel":"null"}],"isRequired":true,"uniqueKey":"oneOf.5.data.lat","typeLabel":"number\u003cdouble> | null"},"lng":{"oneOf":[{"type":"number","format":"double","isRequired":true,"uniqueKey":"oneOf.5.data.lng.oneOf.0","typeLabel":"number\u003cdouble>"},{"type":"null","format":"double","isRequired":true,"uniqueKey":"oneOf.5.data.lng.oneOf.1","typeLabel":"null"}],"isRequired":true,"uniqueKey":"oneOf.5.data.lng","typeLabel":"number\u003cdouble> | null"},"pickup_notes":{"oneOf":[{"type":"string","description":"Standing instructions for the courier collecting here.","isRequired":true,"uniqueKey":"oneOf.5.data.pickup_notes.oneOf.0","typeLabel":"string"},{"type":"null","description":"Standing instructions for the courier collecting here.","isRequired":true,"uniqueKey":"oneOf.5.data.pickup_notes.oneOf.1","typeLabel":"null"}],"isRequired":true,"uniqueKey":"oneOf.5.data.pickup_notes","typeLabel":"string | null"},"timezone":{"type":"string","description":"The IANA zone the store keeps its hours in, normalized to one\nspelling per zone. Derived from the store's coordinates, and\nre-derived whenever the store's position moves. A zone you send\nyourself is used only when the position cannot answer (a store with\nno coordinates, or a position no zone claims), and one that\ndisagrees with the position is neither stored nor treated as an\nerror.\n","example":"America/Mexico_City","isRequired":true,"uniqueKey":"oneOf.5.data.timezone","typeLabel":"string"},"default_business_fee_share":{"type":"integer","minimum":0,"maximum":100,"description":"The share of the delivery fee this store covers by default, as a\npercentage. The rest is charged to the customer. In force only when\n`default_fee_split_mode` is `percent`; in either amount mode this is\nthe percentage the store keeps for when it goes back to one.\n","isRequired":true,"uniqueKey":"oneOf.5.data.default_business_fee_share","typeLabel":"integer"},"default_fee_split_mode":{"type":"string","enum":["percent","business_amount","customer_amount"],"description":"Which shape this store's default split has, and therefore which of\nthe two fields above and below is in force. `percent` splits the fee\nby `default_business_fee_share`; `business_amount` means the store\ncovers up to `default_fee_split_amount_cents` of it and the customer\npays the rest; `customer_amount` is the mirror, the customer paying\nup to that amount and the store covering the rest.\n\nRead-only. It is set by the restaurant in its own Listo console, and\nsending `default_business_fee_share` on a create or an update moves\nthe store back to `percent`.\n","isRequired":true,"uniqueKey":"oneOf.5.data.default_fee_split_mode","typeLabel":"enum\u003cstring>"},"default_fee_split_amount_cents":{"oneOf":[{"type":"integer","minimum":0,"description":"The amount the two amount modes divide the fee by, in cents. Null in\n`percent` mode, and never null in either amount mode. Read-only.\n","isRequired":true,"uniqueKey":"oneOf.5.data.default_fee_split_amount_cents.oneOf.0","typeLabel":"integer"},{"type":"null","minimum":0,"description":"The amount the two amount modes divide the fee by, in cents. Null in\n`percent` mode, and never null in either amount mode. Read-only.\n","isRequired":true,"uniqueKey":"oneOf.5.data.default_fee_split_amount_cents.oneOf.1","typeLabel":"null"}],"isRequired":true,"uniqueKey":"oneOf.5.data.default_fee_split_amount_cents","typeLabel":"integer | null"},"access_tier":{"type":"string","enum":["api_only","wallet","full"],"description":"How much of Listo the store itself uses. An `api_only` store's\ndeliveries spend your balance, and a `wallet` or `full` store's\nspend its own; `billing` says which. Writable on create and update,\nand always `api_only` on a test store. A live store of an account\nwhose restaurants pay their own Plan Listo cannot be `api_only`: it\nhas no console to buy a plan from, so a create or an update that\nasks for it is refused with `422 validation_failed` and\n`param: \"access_tier\"`.\n","isRequired":true,"uniqueKey":"oneOf.5.data.access_tier","typeLabel":"enum\u003cstring>"},"markup_cents":{"type":"integer","minimum":0,"description":"Your own markup on every delivery of this store, in cents. It is\nadded to the delivery fee, split with the customer like the rest of\nthe fee, and credited to your balance when the delivery is\ndelivered. Writable on create and update.\n","isRequired":true,"uniqueKey":"oneOf.5.data.markup_cents","typeLabel":"integer"},"billing":{"type":"string","enum":["partner","store"],"description":"Whose balance pays this store's deliveries, read off `access_tier`\nso you never have to derive it: `partner` is yours, `store` is the\nstore's own. Read-only. It is not who pays the store's plan, which\nis `plan.paid_by`.\n","isRequired":true,"uniqueKey":"oneOf.5.data.billing","typeLabel":"enum\u003cstring>"},"test":{"type":"boolean","isRequired":true,"uniqueKey":"oneOf.5.data.test","typeLabel":"boolean"},"created_at":{"type":"string","format":"date-time","isRequired":true,"uniqueKey":"oneOf.5.data.created_at","typeLabel":"string\u003cdate-time>"},"plan":{"oneOf":[{"description":"The store's Plan Listo, or `null` when the store needs no plan: a\ntest store, or a live store created before Plan Listo existed, which\nkeeps requesting couriers without one. It is also `null` when the\nstore pays its own plan (every store of an account whose stores pay\ntheir own Plan Listo) and the restaurant has not bought one yet: the\nrestaurant buys it in its own console, and there is nothing for you\nto pay or to reactivate. It is also `null` for a store of a partner\non pricing with no Plan Listo, which needs no plan. When it is an\nobject every\nkey is present, and the ones that do not apply are `null`. See\n[Plan and billing](https://docs.listo.delivery/en/guides/plan-and-billing).\n","type":"object","properties":{"status":{"type":"string","enum":["active","past_due","canceling","canceled","awaiting_payment"],"description":"`active` is paid up and renews on `next_charge_on` (null on a\nplan that is passing to the restaurant, see `pending_paid_by`). `past_due`\nhas an unpaid month, and its deliveries are refused with `402\nplan_required` until the charge goes through. `awaiting_payment`\nis a store whose first month your balance and card could not\ncover: it holds no plan yet, `price_cents` is the price it\nwill be charged before IVA (the amount needed to pay is that\nplus IVA), every date is null, its deliveries are refused with\n`402 plan_required`, and Listo charges it by itself as soon as\nyour balance or card covers it. `canceling` was\ncanceled and is served up to the day before `ends_on`.\n`canceled` has ended, and can be restarted.\n","isRequired":true,"uniqueKey":"oneOf.5.data.plan.oneOf.0.status","typeLabel":"enum\u003cstring>"},"price_cents":{"type":"integer","description":"What one month of this store's plan costs you, before IVA: your\nprice, even while a restaurant that connected to you is still\npaying its own plan. When `paid_by` is `store` because the\nstore pays its own plan, it is the price of one `interval` of\nthe restaurant's own plan, which is not yours to pay.\n","example":199000,"isRequired":true,"uniqueKey":"oneOf.5.data.plan.oneOf.0.price_cents","typeLabel":"integer"},"currency":{"type":"string","example":"MXN","isRequired":true,"uniqueKey":"oneOf.5.data.plan.oneOf.0.currency","typeLabel":"string"},"interval":{"type":"string","description":"How long one period of this plan is, and the cycle `price_cents`\nis the price of. `month` for every plan you pay. A store that\npays its own plan reports the interval its restaurant bought,\nso `year` is a restaurant that paid twelve months at once.\n","example":"month","isRequired":true,"uniqueKey":"oneOf.5.data.plan.oneOf.0.interval","typeLabel":"string"},"current_period_ends_on":{"oneOf":[{"type":"string","format":"date","description":"The last day of the current period, already paid unless\n`status` is `past_due`.\n","isRequired":true,"uniqueKey":"oneOf.5.data.plan.oneOf.0.current_period_ends_on.oneOf.0","typeLabel":"string\u003cdate>"},{"type":"null","format":"date","description":"The last day of the current period, already paid unless\n`status` is `past_due`.\n","isRequired":true,"uniqueKey":"oneOf.5.data.plan.oneOf.0.current_period_ends_on.oneOf.1","typeLabel":"null"}],"isRequired":true,"uniqueKey":"oneOf.5.data.plan.oneOf.0.current_period_ends_on","typeLabel":"string\u003cdate> | null"},"next_charge_on":{"oneOf":[{"type":"string","format":"date","description":"The day you are charged next: the next renewal, or, while a\nrestaurant that connected to you still pays its own plan, your\nfirst charge. Null once the plan is ending or has ended, and\nnull while it is `past_due`: the month owed is charged the\nmoment your balance or saved card allows, and retried every\nday until it is paid. Null while `courtesy` is true, too. Null\nas well on a plan you pay that is passing to the restaurant\n(`pending_paid_by` is `store`): you pay the period you are in\nand nothing after it. When `paid_by` is `store` because the\nstore pays its own plan, it is the day the restaurant's own plan\nrenews, not a charge to you.\n","isRequired":true,"uniqueKey":"oneOf.5.data.plan.oneOf.0.next_charge_on.oneOf.0","typeLabel":"string\u003cdate>"},{"type":"null","format":"date","description":"The day you are charged next: the next renewal, or, while a\nrestaurant that connected to you still pays its own plan, your\nfirst charge. Null once the plan is ending or has ended, and\nnull while it is `past_due`: the month owed is charged the\nmoment your balance or saved card allows, and retried every\nday until it is paid. Null while `courtesy` is true, too. Null\nas well on a plan you pay that is passing to the restaurant\n(`pending_paid_by` is `store`): you pay the period you are in\nand nothing after it. When `paid_by` is `store` because the\nstore pays its own plan, it is the day the restaurant's own plan\nrenews, not a charge to you.\n","isRequired":true,"uniqueKey":"oneOf.5.data.plan.oneOf.0.next_charge_on.oneOf.1","typeLabel":"null"}],"isRequired":true,"uniqueKey":"oneOf.5.data.plan.oneOf.0.next_charge_on","typeLabel":"string\u003cdate> | null"},"canceled_at":{"oneOf":[{"type":"string","format":"date-time","description":"When you canceled the plan.","isRequired":true,"uniqueKey":"oneOf.5.data.plan.oneOf.0.canceled_at.oneOf.0","typeLabel":"string\u003cdate-time>"},{"type":"null","format":"date-time","description":"When you canceled the plan.","isRequired":true,"uniqueKey":"oneOf.5.data.plan.oneOf.0.canceled_at.oneOf.1","typeLabel":"null"}],"isRequired":true,"uniqueKey":"oneOf.5.data.plan.oneOf.0.canceled_at","typeLabel":"string\u003cdate-time> | null"},"ends_on":{"oneOf":[{"type":"string","format":"date","description":"The day the plan stops serving the store, which is the day after\nthe last day paid, or the day a plan whose charge was pending was\ncanceled. Null unless the plan is ending or has ended.\n","isRequired":true,"uniqueKey":"oneOf.5.data.plan.oneOf.0.ends_on.oneOf.0","typeLabel":"string\u003cdate>"},{"type":"null","format":"date","description":"The day the plan stops serving the store, which is the day after\nthe last day paid, or the day a plan whose charge was pending was\ncanceled. Null unless the plan is ending or has ended.\n","isRequired":true,"uniqueKey":"oneOf.5.data.plan.oneOf.0.ends_on.oneOf.1","typeLabel":"null"}],"isRequired":true,"uniqueKey":"oneOf.5.data.plan.oneOf.0.ends_on","typeLabel":"string\u003cdate> | null"},"paid_by":{"type":"string","enum":["partner","store"],"description":"Who pays this plan: `partner`, which is you, or `store`, the\nrestaurant itself. `store` is a restaurant that connected to you\nand still pays its own plan, and every store that pays its own\nPlan Listo because your account is set up that way; none of\nthose is yours to pay.\n","isRequired":true,"uniqueKey":"oneOf.5.data.plan.oneOf.0.paid_by","typeLabel":"enum\u003cstring>"},"pending_paid_by":{"oneOf":[{"type":"string","description":"Who will pay it from `pending_paid_by_on`, when that is about to\nchange, or null. `partner` is you: a restaurant that connected to\nyou and still pays its own plan, until the renewal you pay from.\n`store` is the restaurant: a plan you pay that passes to the\nrestaurant at its next renewal because your account is set up so\nthat each restaurant pays its own plan. You pay the period you\nare in and nothing after it, so `next_charge_on` is null.\n","isRequired":true,"uniqueKey":"oneOf.5.data.plan.oneOf.0.pending_paid_by.oneOf.0","typeLabel":"string"},{"type":"null","description":"Who will pay it from `pending_paid_by_on`, when that is about to\nchange, or null. `partner` is you: a restaurant that connected to\nyou and still pays its own plan, until the renewal you pay from.\n`store` is the restaurant: a plan you pay that passes to the\nrestaurant at its next renewal because your account is set up so\nthat each restaurant pays its own plan. You pay the period you\nare in and nothing after it, so `next_charge_on` is null.\n","isRequired":true,"uniqueKey":"oneOf.5.data.plan.oneOf.0.pending_paid_by.oneOf.1","typeLabel":"null"}],"isRequired":true,"uniqueKey":"oneOf.5.data.plan.oneOf.0.pending_paid_by","typeLabel":"string | null"},"pending_paid_by_on":{"oneOf":[{"type":"string","format":"date","description":"The date that change lands (the day the new payer's first\nperiod starts), or null.\n","isRequired":true,"uniqueKey":"oneOf.5.data.plan.oneOf.0.pending_paid_by_on.oneOf.0","typeLabel":"string\u003cdate>"},{"type":"null","format":"date","description":"The date that change lands (the day the new payer's first\nperiod starts), or null.\n","isRequired":true,"uniqueKey":"oneOf.5.data.plan.oneOf.0.pending_paid_by_on.oneOf.1","typeLabel":"null"}],"isRequired":true,"uniqueKey":"oneOf.5.data.plan.oneOf.0.pending_paid_by_on","typeLabel":"string\u003cdate> | null"},"courtesy":{"type":"boolean","description":"`courtesy` is true while Listo waives this store's plan: nothing\nis charged and `next_charge_on` is null.\n","isRequired":true,"uniqueKey":"oneOf.5.data.plan.oneOf.0.courtesy","typeLabel":"boolean"}},"required":["status","price_cents","currency","interval","current_period_ends_on","next_charge_on","canceled_at","ends_on","paid_by","pending_paid_by","pending_paid_by_on","courtesy"],"isRequired":true,"uniqueKey":"oneOf.5.data.plan.oneOf.0","typeLabel":"object"},{"description":"The store's Plan Listo, or `null` when the store needs no plan: a\ntest store, or a live store created before Plan Listo existed, which\nkeeps requesting couriers without one. It is also `null` when the\nstore pays its own plan (every store of an account whose stores pay\ntheir own Plan Listo) and the restaurant has not bought one yet: the\nrestaurant buys it in its own console, and there is nothing for you\nto pay or to reactivate. It is also `null` for a store of a partner\non pricing with no Plan Listo, which needs no plan. When it is an\nobject every\nkey is present, and the ones that do not apply are `null`. See\n[Plan and billing](https://docs.listo.delivery/en/guides/plan-and-billing).\n","type":"null","properties":{"status":{"type":"string","enum":["active","past_due","canceling","canceled","awaiting_payment"],"description":"`active` is paid up and renews on `next_charge_on` (null on a\nplan that is passing to the restaurant, see `pending_paid_by`). `past_due`\nhas an unpaid month, and its deliveries are refused with `402\nplan_required` until the charge goes through. `awaiting_payment`\nis a store whose first month your balance and card could not\ncover: it holds no plan yet, `price_cents` is the price it\nwill be charged before IVA (the amount needed to pay is that\nplus IVA), every date is null, its deliveries are refused with\n`402 plan_required`, and Listo charges it by itself as soon as\nyour balance or card covers it. `canceling` was\ncanceled and is served up to the day before `ends_on`.\n`canceled` has ended, and can be restarted.\n"},"price_cents":{"type":"integer","description":"What one month of this store's plan costs you, before IVA: your\nprice, even while a restaurant that connected to you is still\npaying its own plan. When `paid_by` is `store` because the\nstore pays its own plan, it is the price of one `interval` of\nthe restaurant's own plan, which is not yours to pay.\n","example":199000},"currency":{"type":"string","example":"MXN"},"interval":{"type":"string","description":"How long one period of this plan is, and the cycle `price_cents`\nis the price of. `month` for every plan you pay. A store that\npays its own plan reports the interval its restaurant bought,\nso `year` is a restaurant that paid twelve months at once.\n","example":"month"},"current_period_ends_on":{"oneOf":[{"type":"string","format":"date","description":"The last day of the current period, already paid unless\n`status` is `past_due`.\n"},{"type":"null","format":"date","description":"The last day of the current period, already paid unless\n`status` is `past_due`.\n"}]},"next_charge_on":{"oneOf":[{"type":"string","format":"date","description":"The day you are charged next: the next renewal, or, while a\nrestaurant that connected to you still pays its own plan, your\nfirst charge. Null once the plan is ending or has ended, and\nnull while it is `past_due`: the month owed is charged the\nmoment your balance or saved card allows, and retried every\nday until it is paid. Null while `courtesy` is true, too. Null\nas well on a plan you pay that is passing to the restaurant\n(`pending_paid_by` is `store`): you pay the period you are in\nand nothing after it. When `paid_by` is `store` because the\nstore pays its own plan, it is the day the restaurant's own plan\nrenews, not a charge to you.\n"},{"type":"null","format":"date","description":"The day you are charged next: the next renewal, or, while a\nrestaurant that connected to you still pays its own plan, your\nfirst charge. Null once the plan is ending or has ended, and\nnull while it is `past_due`: the month owed is charged the\nmoment your balance or saved card allows, and retried every\nday until it is paid. Null while `courtesy` is true, too. Null\nas well on a plan you pay that is passing to the restaurant\n(`pending_paid_by` is `store`): you pay the period you are in\nand nothing after it. When `paid_by` is `store` because the\nstore pays its own plan, it is the day the restaurant's own plan\nrenews, not a charge to you.\n"}]},"canceled_at":{"oneOf":[{"type":"string","format":"date-time","description":"When you canceled the plan."},{"type":"null","format":"date-time","description":"When you canceled the plan."}]},"ends_on":{"oneOf":[{"type":"string","format":"date","description":"The day the plan stops serving the store, which is the day after\nthe last day paid, or the day a plan whose charge was pending was\ncanceled. Null unless the plan is ending or has ended.\n"},{"type":"null","format":"date","description":"The day the plan stops serving the store, which is the day after\nthe last day paid, or the day a plan whose charge was pending was\ncanceled. Null unless the plan is ending or has ended.\n"}]},"paid_by":{"type":"string","enum":["partner","store"],"description":"Who pays this plan: `partner`, which is you, or `store`, the\nrestaurant itself. `store` is a restaurant that connected to you\nand still pays its own plan, and every store that pays its own\nPlan Listo because your account is set up that way; none of\nthose is yours to pay.\n"},"pending_paid_by":{"oneOf":[{"type":"string","description":"Who will pay it from `pending_paid_by_on`, when that is about to\nchange, or null. `partner` is you: a restaurant that connected to\nyou and still pays its own plan, until the renewal you pay from.\n`store` is the restaurant: a plan you pay that passes to the\nrestaurant at its next renewal because your account is set up so\nthat each restaurant pays its own plan. You pay the period you\nare in and nothing after it, so `next_charge_on` is null.\n"},{"type":"null","description":"Who will pay it from `pending_paid_by_on`, when that is about to\nchange, or null. `partner` is you: a restaurant that connected to\nyou and still pays its own plan, until the renewal you pay from.\n`store` is the restaurant: a plan you pay that passes to the\nrestaurant at its next renewal because your account is set up so\nthat each restaurant pays its own plan. You pay the period you\nare in and nothing after it, so `next_charge_on` is null.\n"}]},"pending_paid_by_on":{"oneOf":[{"type":"string","format":"date","description":"The date that change lands (the day the new payer's first\nperiod starts), or null.\n"},{"type":"null","format":"date","description":"The date that change lands (the day the new payer's first\nperiod starts), or null.\n"}]},"courtesy":{"type":"boolean","description":"`courtesy` is true while Listo waives this store's plan: nothing\nis charged and `next_charge_on` is null.\n"}},"required":["status","price_cents","currency","interval","current_period_ends_on","next_charge_on","canceled_at","ends_on","paid_by","pending_paid_by","pending_paid_by_on","courtesy"],"isRequired":true,"uniqueKey":"oneOf.5.data.plan.oneOf.1","typeLabel":"null"}],"isRequired":true,"uniqueKey":"oneOf.5.data.plan","typeLabel":"object | null"}},"required":["id","external_id","name","phone","street","apt_unit","lat","lng","pickup_notes","timezone","default_business_fee_share","default_fee_split_mode","default_fee_split_amount_cents","access_tier","markup_cents","billing","test","created_at","plan"],"isRequired":true,"uniqueKey":"oneOf.5.data","typeLabel":"object"},"test":{"type":"boolean","description":"Present, and true, only on a test event you asked for with\n`POST /v1/test_webhooks`. A real event does not carry the field at\nall. A test event's `data` is a sample whose ids resolve to nothing.\n","example":true,"uniqueKey":"oneOf.5.test","typeLabel":"boolean"}},"uniqueKey":"oneOf.5","typeLabel":"object"}],"uniqueKey":"","typeLabel":"object"},"example":{"id":"evt_9pQ2vX7mKdR4tYb1nZ3sLwCe","type":"delivery.status_changed","created_at":"2026-11-06T08:49:43Z","data":{"id":"dlv_test_sample_000000000000","external_id":"order-841","origin":"api","code":"LS-2048","status":"courier_assigned","store_id":"st_test_sample_00000000000000","test":false,"payment":{"method":"prepaid","status":"paid","url":null,"cash_to_collect_cents":null,"paid_at":"2026-07-28T18:41:03Z"},"order_value_cents":18000,"fee_cents":6900,"business_fee_cents":6900,"customer_fee_cents":0,"tip_cents":0,"currency":"MXN","quote_id":"qt_test_sample_000000000000","pickup":{"name":"Test Sample Store","street":"Av. Chapultepec 100, Guadalajara","lat":20.6736,"lng":-103.344,"notes":null},"dropoff":{"name":"Test Customer","phone":"+528112345678","street":"Av. Vallarta 200, Guadalajara","apt_unit":null,"lat":20.6766,"lng":-103.3912,"notes":null,"handoff":"meet_at_door"},"manifest":{"items":[{"name":"Tacos","quantity":2,"size":"small"}]},"vehicle":"moto","courier":{"name":"Test Courier","vehicle":"Test motorcycle","vehicle_type":"moto","plate":"TEST-000","phone":{"masked":"+52 81 **** 5678","pin":null},"location":{"lat":20.6745,"lng":-103.3501,"updated_at":"2026-07-28T18:46:00Z"},"imminent":false},"pickup_eta_at":"2026-07-28T18:50:00Z","dropoff_eta_at":"2026-07-28T19:10:00Z","tracking_url":"https://app.listo.delivery/t/test_sample_000000000000","verification":{"pincode":"4821"},"return_verification":{"pincode":null},"proof":null,"proofs":{"pickup":null,"dropoff":null,"return":null},"cancellation":null,"failure_reason":null,"charges":[],"refunds":[],"refunded_cents":0,"refundable_cents":0,"support_reference":null,"pickup_ready_at":null,"requested_at":"2026-07-28T18:41:03Z","courier_assigned_at":"2026-07-28T18:44:00Z","picked_up_at":null,"delivered_at":null,"canceled_at":null,"returned_at":null,"created_at":"2026-07-28T18:41:03Z","updated_at":"2026-07-28T18:46:00Z"},"test":true},"examples":{"Example":{"title":"Example","value":{"id":"evt_9pQ2vX7mKdR4tYb1nZ3sLwCe","type":"delivery.status_changed","created_at":"2026-11-06T08:49:43Z","data":{"id":"dlv_test_sample_000000000000","external_id":"order-841","origin":"api","code":"LS-2048","status":"courier_assigned","store_id":"st_test_sample_00000000000000","test":false,"payment":{"method":"prepaid","status":"paid","url":null,"cash_to_collect_cents":null,"paid_at":"2026-07-28T18:41:03Z"},"order_value_cents":18000,"fee_cents":6900,"business_fee_cents":6900,"customer_fee_cents":0,"tip_cents":0,"currency":"MXN","quote_id":"qt_test_sample_000000000000","pickup":{"name":"Test Sample Store","street":"Av. Chapultepec 100, Guadalajara","lat":20.6736,"lng":-103.344,"notes":null},"dropoff":{"name":"Test Customer","phone":"+528112345678","street":"Av. Vallarta 200, Guadalajara","apt_unit":null,"lat":20.6766,"lng":-103.3912,"notes":null,"handoff":"meet_at_door"},"manifest":{"items":[{"name":"Tacos","quantity":2,"size":"small"}]},"vehicle":"moto","courier":{"name":"Test Courier","vehicle":"Test motorcycle","vehicle_type":"moto","plate":"TEST-000","phone":{"masked":"+52 81 **** 5678","pin":null},"location":{"lat":20.6745,"lng":-103.3501,"updated_at":"2026-07-28T18:46:00Z"},"imminent":false},"pickup_eta_at":"2026-07-28T18:50:00Z","dropoff_eta_at":"2026-07-28T19:10:00Z","tracking_url":"https://app.listo.delivery/t/test_sample_000000000000","verification":{"pincode":"4821"},"return_verification":{"pincode":null},"proof":null,"proofs":{"pickup":null,"dropoff":null,"return":null},"cancellation":null,"failure_reason":null,"charges":[],"refunds":[],"refunded_cents":0,"refundable_cents":0,"support_reference":null,"pickup_ready_at":null,"requested_at":"2026-07-28T18:41:03Z","courier_assigned_at":"2026-07-28T18:44:00Z","picked_up_at":null,"delivered_at":null,"canceled_at":null,"returned_at":null,"created_at":"2026-07-28T18:41:03Z","updated_at":"2026-07-28T18:46:00Z"},"test":true}}},"exampleType":"examples"}},"exampleType":"examples"},"2b60cad3-caa1-48aa-8cc0-86def9166bfd":{"description":"The key is valid and is read-only (`read_only_key`), so it can read but not create, change or cancel anything. Use a key issued without the read-only setting.","content":{"application/json":{"schema":{"type":"object","description":"The body of every 4xx and 5xx answer on this API.","properties":{"error":{"type":"object","description":"What every refusal and every failure looks like. `code` is the only\nfield to branch on; `message` is for a human reading a log and may\nchange wording or language without notice.\n","properties":{"code":{"type":"string","description":"A stable, machine-readable name for what went wrong, such as\n`validation_failed`, `not_found` or `insufficient_balance`. Branch\non this and never on `message`. The set grows additively: handle a\ncode you do not know as the generic failure its status code says it\nis. Every code has a page under `doc_url`.\n","example":"validation_failed","isRequired":true,"uniqueKey":"error.code","typeLabel":"string"},"message":{"type":"string","description":"A sentence for the person debugging. Free to change wording or\nlanguage, so never match on it.\n","example":"order_value_cents is required.","isRequired":true,"uniqueKey":"error.message","typeLabel":"string"},"param":{"oneOf":[{"type":"string","description":"The request field the refusal is about, when one applies, spelled\nas you sent it (`dropoff.street`, `manifest.items`). Null when the\nfailure is not about one field.\n","example":"order_value_cents","isRequired":true,"uniqueKey":"error.param.oneOf.0","typeLabel":"string"},{"type":"null","description":"The request field the refusal is about, when one applies, spelled\nas you sent it (`dropoff.street`, `manifest.items`). Null when the\nfailure is not about one field.\n","example":"order_value_cents","isRequired":true,"uniqueKey":"error.param.oneOf.1","typeLabel":"null"}],"isRequired":true,"uniqueKey":"error.param","typeLabel":"string | null"},"retryable":{"type":"boolean","description":"Whether sending the identical request again could succeed. `false`\nmeans it never will without a change on your side or in the world.\n","example":false,"isRequired":true,"uniqueKey":"error.retryable","typeLabel":"boolean"},"doc_url":{"type":"string","format":"uri","description":"The documentation page for this `code`.","example":"https://docs.listo.delivery/en/errors/validation_failed","isRequired":true,"uniqueKey":"error.doc_url","typeLabel":"string\u003curi>"},"request_id":{"type":"string","description":"Our id for this request, the same value as the `X-Request-Id`\nresponse header. Quote it to support, and filter\n`GET /v1/request_logs` by it.\n","example":"0b1f6c9a-7e2d-4c53-9a41-5d8e3f2a6b10","isRequired":true,"uniqueKey":"error.request_id","typeLabel":"string"}},"required":["code","message","param","retryable","doc_url","request_id"],"isRequired":true,"uniqueKey":"error","typeLabel":"object"}},"required":["error"],"uniqueKey":"","typeLabel":"object"},"examples":{"read_only_key":{"title":"read_only_key","value":{"error":{"code":"read_only_key","message":"This API key is read-only. Use a key without the read-only setting to create, change or cancel anything.","param":null,"retryable":false,"doc_url":"https://docs.listo.delivery/en/errors/read_only_key","request_id":"0b1f6c9a-7e2d-4c53-9a41-5d8e3f2a6b10"}}}},"exampleType":"examples"}},"exampleType":"examples"},"5a50c2f5-34ae-47bd-bf8d-59473ad4b83d":{"description":"The request conflicts with the state of the world. The object is no longer in a state that allows this (`not_cancellable`, `not_reschedulable`, `not_retriable`, `not_editable`, `not_refundable`, `not_reactivatable`, `plan_ended`), the cancellation did not go through (`cancel_failed`), the plan's charge is still with the bank (`charge_in_progress`), the idempotency key was reused with a different body (`idempotency_conflict`, which no retry fixes), the idempotency key is still held by the request that first sent it (`idempotency_conflict`, and once that request has answered the same call with the same key replays its answer), there is no webhook URL configured for the key's mode so there is nowhere to send (`webhook_endpoint_not_configured`), the event is a courier position, which is never sent again (`event_not_resendable`), the email already has a Listo account (`account_exists`), the store's pickup point is still being moved (`pickup_point_pending`), or no courier is free for this trip right now (`no_couriers_available`). Worth repeating unchanged after a few minutes: `cancel_failed`, `charge_in_progress`, `pickup_point_pending`, `no_couriers_available`, and a call refused because its idempotency key is still held (repeat it with the same key). Every other refusal here needs the request or the object to change first.","content":{"application/json":{"schema":{"type":"object","description":"The body of every 4xx and 5xx answer on this API.","properties":{"error":{"type":"object","description":"What every refusal and every failure looks like. `code` is the only\nfield to branch on; `message` is for a human reading a log and may\nchange wording or language without notice.\n","properties":{"code":{"type":"string","description":"A stable, machine-readable name for what went wrong, such as\n`validation_failed`, `not_found` or `insufficient_balance`. Branch\non this and never on `message`. The set grows additively: handle a\ncode you do not know as the generic failure its status code says it\nis. Every code has a page under `doc_url`.\n","example":"validation_failed","isRequired":true,"uniqueKey":"error.code","typeLabel":"string"},"message":{"type":"string","description":"A sentence for the person debugging. Free to change wording or\nlanguage, so never match on it.\n","example":"order_value_cents is required.","isRequired":true,"uniqueKey":"error.message","typeLabel":"string"},"param":{"oneOf":[{"type":"string","description":"The request field the refusal is about, when one applies, spelled\nas you sent it (`dropoff.street`, `manifest.items`). Null when the\nfailure is not about one field.\n","example":"order_value_cents","isRequired":true,"uniqueKey":"error.param.oneOf.0","typeLabel":"string"},{"type":"null","description":"The request field the refusal is about, when one applies, spelled\nas you sent it (`dropoff.street`, `manifest.items`). Null when the\nfailure is not about one field.\n","example":"order_value_cents","isRequired":true,"uniqueKey":"error.param.oneOf.1","typeLabel":"null"}],"isRequired":true,"uniqueKey":"error.param","typeLabel":"string | null"},"retryable":{"type":"boolean","description":"Whether sending the identical request again could succeed. `false`\nmeans it never will without a change on your side or in the world.\n","example":false,"isRequired":true,"uniqueKey":"error.retryable","typeLabel":"boolean"},"doc_url":{"type":"string","format":"uri","description":"The documentation page for this `code`.","example":"https://docs.listo.delivery/en/errors/validation_failed","isRequired":true,"uniqueKey":"error.doc_url","typeLabel":"string\u003curi>"},"request_id":{"type":"string","description":"Our id for this request, the same value as the `X-Request-Id`\nresponse header. Quote it to support, and filter\n`GET /v1/request_logs` by it.\n","example":"0b1f6c9a-7e2d-4c53-9a41-5d8e3f2a6b10","isRequired":true,"uniqueKey":"error.request_id","typeLabel":"string"}},"required":["code","message","param","retryable","doc_url","request_id"],"isRequired":true,"uniqueKey":"error","typeLabel":"object"}},"required":["error"],"uniqueKey":"","typeLabel":"object"},"example":{"error":{"code":"webhook_endpoint_not_configured","message":"There is no webhook URL configured for this mode, so there is nowhere to send it.","param":null,"retryable":false,"doc_url":"https://docs.listo.delivery/en/errors/webhook_endpoint_not_configured","request_id":"0b1f6c9a-7e2d-4c53-9a41-5d8e3f2a6b10"}},"examples":{"Example":{"title":"Example","value":{"error":{"code":"webhook_endpoint_not_configured","message":"There is no webhook URL configured for this mode, so there is nowhere to send it.","param":null,"retryable":false,"doc_url":"https://docs.listo.delivery/en/errors/webhook_endpoint_not_configured","request_id":"0b1f6c9a-7e2d-4c53-9a41-5d8e3f2a6b10"}}}},"exampleType":"examples"}},"exampleType":"examples"},"fa847c57-f1eb-41b2-9e78-e8d3955de6d2":{"description":"The request was understood and refused. `error.code` says why and `error.param` names the offending field when one applies.","content":{"application/json":{"schema":{"type":"object","description":"The body of every 4xx and 5xx answer on this API.","properties":{"error":{"type":"object","description":"What every refusal and every failure looks like. `code` is the only\nfield to branch on; `message` is for a human reading a log and may\nchange wording or language without notice.\n","properties":{"code":{"type":"string","description":"A stable, machine-readable name for what went wrong, such as\n`validation_failed`, `not_found` or `insufficient_balance`. Branch\non this and never on `message`. The set grows additively: handle a\ncode you do not know as the generic failure its status code says it\nis. Every code has a page under `doc_url`.\n","example":"validation_failed","isRequired":true,"uniqueKey":"error.code","typeLabel":"string"},"message":{"type":"string","description":"A sentence for the person debugging. Free to change wording or\nlanguage, so never match on it.\n","example":"order_value_cents is required.","isRequired":true,"uniqueKey":"error.message","typeLabel":"string"},"param":{"oneOf":[{"type":"string","description":"The request field the refusal is about, when one applies, spelled\nas you sent it (`dropoff.street`, `manifest.items`). Null when the\nfailure is not about one field.\n","example":"order_value_cents","isRequired":true,"uniqueKey":"error.param.oneOf.0","typeLabel":"string"},{"type":"null","description":"The request field the refusal is about, when one applies, spelled\nas you sent it (`dropoff.street`, `manifest.items`). Null when the\nfailure is not about one field.\n","example":"order_value_cents","isRequired":true,"uniqueKey":"error.param.oneOf.1","typeLabel":"null"}],"isRequired":true,"uniqueKey":"error.param","typeLabel":"string | null"},"retryable":{"type":"boolean","description":"Whether sending the identical request again could succeed. `false`\nmeans it never will without a change on your side or in the world.\n","example":false,"isRequired":true,"uniqueKey":"error.retryable","typeLabel":"boolean"},"doc_url":{"type":"string","format":"uri","description":"The documentation page for this `code`.","example":"https://docs.listo.delivery/en/errors/validation_failed","isRequired":true,"uniqueKey":"error.doc_url","typeLabel":"string\u003curi>"},"request_id":{"type":"string","description":"Our id for this request, the same value as the `X-Request-Id`\nresponse header. Quote it to support, and filter\n`GET /v1/request_logs` by it.\n","example":"0b1f6c9a-7e2d-4c53-9a41-5d8e3f2a6b10","isRequired":true,"uniqueKey":"error.request_id","typeLabel":"string"}},"required":["code","message","param","retryable","doc_url","request_id"],"isRequired":true,"uniqueKey":"error","typeLabel":"object"}},"required":["error"],"uniqueKey":"","typeLabel":"object"},"example":{"error":{"code":"validation_failed","message":"That is not a webhook event type.","param":"type","retryable":false,"doc_url":"https://docs.listo.delivery/en/errors/validation_failed","request_id":"0b1f6c9a-7e2d-4c53-9a41-5d8e3f2a6b10"}},"examples":{"Example":{"title":"Example","value":{"error":{"code":"validation_failed","message":"That is not a webhook event type.","param":"type","retryable":false,"doc_url":"https://docs.listo.delivery/en/errors/validation_failed","request_id":"0b1f6c9a-7e2d-4c53-9a41-5d8e3f2a6b10"}}}},"exampleType":"examples"}},"exampleType":"examples"},"8ce481e4-bac6-4373-887e-fdec406ee13a":{"description":"Too many requests (`rate_limited`). Back off and retry. A resend refused because the event was already sent again 5 times in the last hour is `resend_limit_reached`, and a test webhook refused because 30 were already sent in the last hour is `test_webhook_limit_reached`; both are worth retrying once the hour has moved on.","content":{"application/json":{"schema":{"type":"object","description":"The body of every 4xx and 5xx answer on this API.","properties":{"error":{"type":"object","description":"What every refusal and every failure looks like. `code` is the only\nfield to branch on; `message` is for a human reading a log and may\nchange wording or language without notice.\n","properties":{"code":{"type":"string","description":"A stable, machine-readable name for what went wrong, such as\n`validation_failed`, `not_found` or `insufficient_balance`. Branch\non this and never on `message`. The set grows additively: handle a\ncode you do not know as the generic failure its status code says it\nis. Every code has a page under `doc_url`.\n","example":"validation_failed","isRequired":true,"uniqueKey":"error.code","typeLabel":"string"},"message":{"type":"string","description":"A sentence for the person debugging. Free to change wording or\nlanguage, so never match on it.\n","example":"order_value_cents is required.","isRequired":true,"uniqueKey":"error.message","typeLabel":"string"},"param":{"oneOf":[{"type":"string","description":"The request field the refusal is about, when one applies, spelled\nas you sent it (`dropoff.street`, `manifest.items`). Null when the\nfailure is not about one field.\n","example":"order_value_cents","isRequired":true,"uniqueKey":"error.param.oneOf.0","typeLabel":"string"},{"type":"null","description":"The request field the refusal is about, when one applies, spelled\nas you sent it (`dropoff.street`, `manifest.items`). Null when the\nfailure is not about one field.\n","example":"order_value_cents","isRequired":true,"uniqueKey":"error.param.oneOf.1","typeLabel":"null"}],"isRequired":true,"uniqueKey":"error.param","typeLabel":"string | null"},"retryable":{"type":"boolean","description":"Whether sending the identical request again could succeed. `false`\nmeans it never will without a change on your side or in the world.\n","example":false,"isRequired":true,"uniqueKey":"error.retryable","typeLabel":"boolean"},"doc_url":{"type":"string","format":"uri","description":"The documentation page for this `code`.","example":"https://docs.listo.delivery/en/errors/validation_failed","isRequired":true,"uniqueKey":"error.doc_url","typeLabel":"string\u003curi>"},"request_id":{"type":"string","description":"Our id for this request, the same value as the `X-Request-Id`\nresponse header. Quote it to support, and filter\n`GET /v1/request_logs` by it.\n","example":"0b1f6c9a-7e2d-4c53-9a41-5d8e3f2a6b10","isRequired":true,"uniqueKey":"error.request_id","typeLabel":"string"}},"required":["code","message","param","retryable","doc_url","request_id"],"isRequired":true,"uniqueKey":"error","typeLabel":"object"}},"required":["error"],"uniqueKey":"","typeLabel":"object"},"example":{"error":{"code":"test_webhook_limit_reached","message":"30 test webhooks were already sent in the last hour. Try again later.","param":null,"retryable":true,"doc_url":"https://docs.listo.delivery/en/errors/test_webhook_limit_reached","request_id":"0b1f6c9a-7e2d-4c53-9a41-5d8e3f2a6b10"}},"examples":{"Example":{"title":"Example","value":{"error":{"code":"test_webhook_limit_reached","message":"30 test webhooks were already sent in the last hour. Try again later.","param":null,"retryable":true,"doc_url":"https://docs.listo.delivery/en/errors/test_webhook_limit_reached","request_id":"0b1f6c9a-7e2d-4c53-9a41-5d8e3f2a6b10"}}}},"exampleType":"examples"}},"exampleType":"examples"}},"security":{"cd7f4a15-648b-441e-9a2d-1d5b4d0b3653":{"BearerAuth":{"type":"http","scheme":"bearer","description":"Your API key, sent as `Authorization: Bearer \u003ckey>`. Live and test keys are separate; the key you send decides which world the call acts in. To try calls, use a test key (it starts with `lst_test_`): no real courier is sent and no real money moves, but webhooks fire and the `dropoff.phone` you give can receive WhatsApp messages, so use your own number. A live key (it starts with `lst_live_`) books and charges real deliveries.","scopes":[],"schemeName":"BearerAuth"}}},"servers":{"a658606d-cd78-44bb-b1d3-622847e198a1":{"url":"https://api.listo.delivery"}},"processedSecurityOptions":[{"schemes":[{"scheme":{"type":"http","scheme":"bearer","description":"Your API key, sent as `Authorization: Bearer \u003ckey>`. Live and test keys are separate; the key you send decides which world the call acts in. To try calls, use a test key (it starts with `lst_test_`): no real courier is sent and no real money moves, but webhooks fire and the `dropoff.phone` you give can receive WhatsApp messages, so use your own number. A live key (it starts with `lst_live_`) books and charges real deliveries.","scopes":[],"schemeName":"BearerAuth"},"schema":{"title":"Bearer Auth","type":"string","isRequired":true,"description":"Your API key, sent as `Authorization: Bearer \u003ckey>`. Live and test keys are separate; the key you send decides which world the call acts in. To try calls, use a test key (it starts with `lst_test_`): no real courier is sent and no real money moves, but webhooks fire and the `dropoff.phone` you give can receive WhatsApp messages, so use your own number. A live key (it starts with `lst_live_`) books and charges real deliveries.","format":"bearer","typeLabel":"string\u003cbearer>","deprecated":false},"schemeName":"BearerAuth","name":"Authorization"}],"title":"BearerAuth"}]},"originalFileLocation":"openapi/en.yaml"},"subdomain":"listo-c5a11a00","siteName":"Listo Partner API","title":"Send a test webhook - Listo Partner API","navMaps":{"firstHrefInVersion":{},"firstHrefInLanguage":{"en":{"href":"/api-reference/events/send-a-test-webhook","matchLevel":0},"es":{"href":"/es/api-reference/events/send-a-test-webhook","matchLevel":1}}},"lastModified":"2026-11-07T01:48:55.586Z","originalFileLocation":"api-reference/events/send-a-test-webhook.mdx","locale":"en"},"headHtml":"\u003cscript data-mint-head>(function(){var d=document.documentElement,p=null;if(!p){try{p=localStorage.getItem(\"isDarkMode\")}catch(e){}if(p==='true')p='dark';else if(p==='false')p='light';if(p!=='light'\u0026\u0026p!=='dark'\u0026\u0026p!=='system')p=\"system\"}var r=p==='system'?(matchMedia(\"(prefers-color-scheme: dark)\").matches?'dark':'light'):p;d.classList.remove(r==='dark'?'light':'dark');d.classList.add(r);d.setAttribute(\"data-theme-preference\",p)})();\u003c/script>\u003cmeta data-mint-head name=\"description\" content=\"Sends a synthetic event of one published type to your webhook URL, so you can exercise an endpoint without placing an order. The answer is 202 with the event as your endpoint receives it, and the attempt appears on GET /v1/webhook_deliveries like any other. - test: true is on the envelope. A real event never carries the field. Branch on it before doing anything with consequences. - Its ids resolve to nothing. data is a realistic sample of the type, but the delivery, store, withdrawal or quote it names does not exist, so reading it back answers 404. - Either mode. A test key sends to your test endpoint and a live key to your live one. The live endpoint does receive the test event. - Thirty an hour per mode. The thirty-first is 429 test_webhook_limit_reached, retryable once the hour has moved on. Retry-After says how many seconds until you can send again. A type that is not a published event type is 422 validation_failed with param: \u0026quot;type\u0026quot;. With no webhook URL configured for the key\u0026#x27;s mode the answer is 409 webhook_endpoint_not_configured.\">\u003cmeta data-mint-head name=\"application-name\" content=\"Listo Partner API\">\u003cmeta data-mint-head name=\"generator\" content=\"Mintlify\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"192x192\" href=\"/mintlify-assets/_mintlify/favicons/listo-c5a11a00/GMBEN5uWEX-r6cRJ/_generated/favicon/android-chrome-192x192.png\" media=\"(prefers-color-scheme: light)\">\u003clink data-mint-head rel=\"apple-touch-icon\" type=\"image/png\" sizes=\"180x180\" href=\"/mintlify-assets/_mintlify/favicons/listo-c5a11a00/GMBEN5uWEX-r6cRJ/_generated/favicon/apple-touch-icon.png\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"16x16\" href=\"/mintlify-assets/_mintlify/favicons/listo-c5a11a00/GMBEN5uWEX-r6cRJ/_generated/favicon/favicon-16x16.png\" media=\"(prefers-color-scheme: light)\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"32x32\" href=\"/mintlify-assets/_mintlify/favicons/listo-c5a11a00/GMBEN5uWEX-r6cRJ/_generated/favicon/favicon-32x32.png\" media=\"(prefers-color-scheme: light)\">\u003clink data-mint-head rel=\"shortcut icon\" type=\"image/x-icon\" href=\"/mintlify-assets/_mintlify/favicons/listo-c5a11a00/GMBEN5uWEX-r6cRJ/_generated/favicon/favicon.ico\" media=\"(prefers-color-scheme: light)\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"192x192\" href=\"/mintlify-assets/_mintlify/favicons/listo-c5a11a00/GMBEN5uWEX-r6cRJ/_generated/favicon-dark/android-chrome-192x192.png\" media=\"(prefers-color-scheme: dark)\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"16x16\" href=\"/mintlify-assets/_mintlify/favicons/listo-c5a11a00/GMBEN5uWEX-r6cRJ/_generated/favicon-dark/favicon-16x16.png\" media=\"(prefers-color-scheme: dark)\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"32x32\" href=\"/mintlify-assets/_mintlify/favicons/listo-c5a11a00/GMBEN5uWEX-r6cRJ/_generated/favicon-dark/favicon-32x32.png\" media=\"(prefers-color-scheme: dark)\">\u003clink data-mint-head rel=\"shortcut icon\" type=\"image/x-icon\" href=\"/mintlify-assets/_mintlify/favicons/listo-c5a11a00/GMBEN5uWEX-r6cRJ/_generated/favicon-dark/favicon.ico\" media=\"(prefers-color-scheme: dark)\">\u003cmeta data-mint-head property=\"og:title\" content=\"Send a test webhook - Listo Partner API\">\u003cmeta data-mint-head property=\"og:description\" content=\"Sends a synthetic event of one published type to your webhook URL, so you can exercise an endpoint without placing an order. The answer is 202 with the event as your endpoint receives it, and the attempt appears on GET /v1/webhook_deliveries like any other. - test: true is on the envelope. A real event never carries the field. Branch on it before doing anything with consequences. - Its ids resolve to nothing. data is a realistic sample of the type, but the delivery, store, withdrawal or quote it names does not exist, so reading it back answers 404. - Either mode. A test key sends to your test endpoint and a live key to your live one. The live endpoint does receive the test event. - Thirty an hour per mode. The thirty-first is 429 test_webhook_limit_reached, retryable once the hour has moved on. Retry-After says how many seconds until you can send again. A type that is not a published event type is 422 validation_failed with param: \u0026quot;type\u0026quot;. With no webhook URL configured for the key\u0026#x27;s mode the answer is 409 webhook_endpoint_not_configured.\">\u003cmeta data-mint-head property=\"og:site_name\" content=\"Listo Partner API\">\u003cmeta data-mint-head property=\"og:url\" content=\"https://docs.listo.delivery/api-reference/events/send-a-test-webhook\">\u003cmeta data-mint-head property=\"og:type\" content=\"website\">\u003cmeta data-mint-head property=\"og:image\" content=\"https://listo-c5a11a00.mintlify.site/_mintlify/api/og/v2?title=Send+a+test+webhook\u0026amp;description=Sends+a+synthetic+event+of+one+published+%60type%60+to+your+webhook+URL%2C+so%0Ayou+can+exercise+an+endpoint+without+placing+an+order.+The+answer+is+%60202%60%0Awith+the+even\u0026amp;theme=77fcfc9066d8b9eb9850b729\u0026amp;signature=d64bf100fd6b8ab9dea582e00dd5467ee807603cd78637b67391634cce582f8b\">\u003cmeta data-mint-head property=\"og:image:width\" content=\"1200\">\u003cmeta data-mint-head property=\"og:image:height\" content=\"630\">\u003cmeta data-mint-head name=\"twitter:card\" content=\"summary_large_image\">\u003cmeta data-mint-head name=\"twitter:title\" content=\"Send a test webhook - Listo Partner API\">\u003cmeta data-mint-head name=\"twitter:description\" content=\"Sends a synthetic event of one published type to your webhook URL, so you can exercise an endpoint without placing an order. The answer is 202 with the event as your endpoint receives it, and the attempt appears on GET /v1/webhook_deliveries like any other. - test: true is on the envelope. A real event never carries the field. Branch on it before doing anything with consequences. - Its ids resolve to nothing. data is a realistic sample of the type, but the delivery, store, withdrawal or quote it names does not exist, so reading it back answers 404. - Either mode. A test key sends to your test endpoint and a live key to your live one. The live endpoint does receive the test event. - Thirty an hour per mode. The thirty-first is 429 test_webhook_limit_reached, retryable once the hour has moved on. Retry-After says how many seconds until you can send again. A type that is not a published event type is 422 validation_failed with param: \u0026quot;type\u0026quot;. With no webhook URL configured for the key\u0026#x27;s mode the answer is 409 webhook_endpoint_not_configured.\">\u003cmeta data-mint-head name=\"twitter:image\" content=\"https://listo-c5a11a00.mintlify.site/_mintlify/api/og/v2?title=Send+a+test+webhook\u0026amp;description=Sends+a+synthetic+event+of+one+published+%60type%60+to+your+webhook+URL%2C+so%0Ayou+can+exercise+an+endpoint+without+placing+an+order.+The+answer+is+%60202%60%0Awith+the+even\u0026amp;theme=77fcfc9066d8b9eb9850b729\u0026amp;signature=d64bf100fd6b8ab9dea582e00dd5467ee807603cd78637b67391634cce582f8b\">\u003cmeta data-mint-head name=\"twitter:image:width\" content=\"1200\">\u003cmeta data-mint-head name=\"twitter:image:height\" content=\"630\">\u003cmeta data-mint-head name=\"msapplication-config\" content=\"/mintlify-assets/_mintlify/favicons/listo-c5a11a00/GMBEN5uWEX-r6cRJ/_generated/favicon/browserconfig.xml\">\u003cmeta data-mint-head name=\"apple-mobile-web-app-title\" content=\"Listo Partner API\">\u003cmeta data-mint-head name=\"msapplication-TileColor\" content=\"#15171C\">\u003clink data-mint-head rel=\"canonical\" href=\"https://docs.listo.delivery/api-reference/events/send-a-test-webhook\">\u003clink data-mint-head rel=\"alternate\" type=\"application/xml\" href=\"/sitemap.xml\">\u003clink data-mint-head rel=\"alternate\" type=\"text/markdown\" href=\"/api-reference/events/send-a-test-webhook.md\">\u003clink data-mint-head rel=\"alternate\" hreflang=\"en\" href=\"https://docs.listo.delivery/api-reference/events/send-a-test-webhook\">\u003clink data-mint-head rel=\"alternate\" hreflang=\"es\" href=\"https://docs.listo.delivery/es/api-reference/events/send-a-test-webhook\">\u003clink data-mint-head rel=\"alternate\" hreflang=\"x-default\" href=\"https://docs.listo.delivery/api-reference/events/send-a-test-webhook\">\u003cscript data-mint-head type=\"application/ld+json\">{\"@context\":\"https://schema.org\",\"@graph\":[{\"@type\":\"Organization\",\"@id\":\"https://docs.listo.delivery/#organization\",\"name\":\"Listo Partner API\",\"url\":\"https://docs.listo.delivery\",\"logo\":{\"@type\":\"ImageObject\",\"url\":\"https://mintcdn.com/listo-c5a11a00/mreCwXzcEA2bSZog/logo/light.svg?fit=max\u0026auto=format\u0026n=mreCwXzcEA2bSZog\u0026q=85\u0026s=da2b28d464dc6987329dfd5971085dd7\"}},{\"@type\":\"WebSite\",\"@id\":\"https://docs.listo.delivery#website\",\"name\":\"Listo Partner API\",\"url\":\"https://docs.listo.delivery\",\"publisher\":{\"@id\":\"https://docs.listo.delivery/#organization\"}},{\"@type\":\"WebPage\",\"@id\":\"https://docs.listo.delivery/api-reference/events/send-a-test-webhook#webpage\",\"url\":\"https://docs.listo.delivery/api-reference/events/send-a-test-webhook\",\"name\":\"Send a test webhook\",\"description\":\"Sends a synthetic event of one published type to your webhook URL, so you can exercise an endpoint without placing an order. The answer is 202 with the event as your endpoint receives it, and the attempt appears on GET /v1/webhook_deliveries like any other. - test: true is on the envelope. A real event never carries the field. Branch on it before doing anything with consequences. - Its ids resolve to nothing. data is a realistic sample of the type, but the delivery, store, withdrawal or quote it names does not exist, so reading it back answers 404. - Either mode. A test key sends to your test endpoint and a live key to your live one. The live endpoint does receive the test event. - Thirty an hour per mode. The thirty-first is 429 test_webhook_limit_reached, retryable once the hour has moved on. Retry-After says how many seconds until you can send again. A type that is not a published event type is 422 validation_failed with param: \\\"type\\\". With no webhook URL configured for the key's mode the answer is 409 webhook_endpoint_not_configured.\",\"dateModified\":\"2026-11-07T01:48:55.586Z\",\"isPartOf\":{\"@id\":\"https://docs.listo.delivery#website\"},\"breadcrumb\":{\"@id\":\"https://docs.listo.delivery/api-reference/events/send-a-test-webhook#breadcrumb\"}},{\"@type\":\"BreadcrumbList\",\"@id\":\"https://docs.listo.delivery/api-reference/events/send-a-test-webhook#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Reference\",\"item\":\"https://docs.listo.delivery/api-reference/balance/read-your-prepaid-balance\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Events\",\"item\":\"https://docs.listo.delivery/api-reference/events/list-your-webhook-events\"},{\"@type\":\"ListItem\",\"position\":3,\"name\":\"Send a test webhook\",\"item\":\"https://docs.listo.delivery/api-reference/events/send-a-test-webhook\"}]},{\"@type\":[\"TechArticle\",\"APIReference\"],\"@id\":\"https://docs.listo.delivery/api-reference/events/send-a-test-webhook#apireference\",\"headline\":\"Send a test webhook\",\"name\":\"Send a test webhook\",\"description\":\"Sends a synthetic event of one published type to your webhook URL, so you can exercise an endpoint without placing an order. The answer is 202 with the event as your endpoint receives it, and the attempt appears on GET /v1/webhook_deliveries like any other. - test: true is on the envelope. A real event never carries the field. Branch on it before doing anything with consequences. - Its ids resolve to nothing. data is a realistic sample of the type, but the delivery, store, withdrawal or quote it names does not exist, so reading it back answers 404. - Either mode. A test key sends to your test endpoint and a live key to your live one. The live endpoint does receive the test event. - Thirty an hour per mode. The thirty-first is 429 test_webhook_limit_reached, retryable once the hour has moved on. Retry-After says how many seconds until you can send again. A type that is not a published event type is 422 validation_failed with param: \\\"type\\\". With no webhook URL configured for the key's mode the answer is 409 webhook_endpoint_not_configured.\",\"url\":\"https://docs.listo.delivery/api-reference/events/send-a-test-webhook\",\"mainEntityOfPage\":{\"@id\":\"https://docs.listo.delivery/api-reference/events/send-a-test-webhook#webpage\"},\"dateModified\":\"2026-11-07T01:48:55.586Z\",\"publisher\":{\"@id\":\"https://docs.listo.delivery/#organization\"},\"isPartOf\":{\"@id\":\"https://docs.listo.delivery#website\"}}]}\u003c/script>\u003cscript data-mint-head type=\"application/ld+json\">{\"@context\":\"https://schema.org\",\"@type\":\"WebSite\",\"name\":\"Listo Partner API\",\"creator\":{\"@type\":\"Organization\",\"name\":\"Mintlify\",\"url\":\"https://mintlify.com\"}}\u003c/script>","siteName":"Listo Partner API","nav":{"global":null,"languages":[{"language":"en","default":true,"navbar":{"links":[{"href":"https://status.listo.delivery","label":"Status"}]},"groups":[{"group":"Get started","pages":[{"title":"Quickstart","href":"/en/quickstart"}]},{"group":"Guides","pages":[{"title":"Quote and create a delivery","href":"/en/guides/quote-and-create"},{"title":"Receive and verify webhooks","href":"/en/guides/webhooks"},{"title":"Debugging your integration","href":"/en/guides/debugging"},{"title":"Build with AI","href":"/en/guides/build-with-ai"},{"title":"Fund your balance and withdraw","href":"/en/guides/balance-and-withdrawals"},{"title":"Go live","href":"/en/guides/go-live"},{"title":"Connect a restaurant that already uses Listo","sidebarTitle":"Connect an existing account","href":"/en/guides/connect-existing-account"},{"title":"Plan and billing","href":"/en/guides/plan-and-billing"},{"title":"Connect Claude, Cursor or Codex","href":"/en/guides/connect-ai-client"}]},{"group":"Errors","expanded":false,"pages":[{"title":"Errors","href":"/en/errors/index"},{"title":"account_exists","href":"/en/errors/account_exists"},{"title":"address_not_found","href":"/en/errors/address_not_found"},{"title":"address_undeliverable","href":"/en/errors/address_undeliverable"},{"title":"cancel_failed","href":"/en/errors/cancel_failed"},{"title":"card_below_minimum","href":"/en/errors/card_below_minimum"},{"title":"card_not_ready","href":"/en/errors/card_not_ready"},{"title":"cash_over_cap","href":"/en/errors/cash_over_cap"},{"title":"charge_in_progress","href":"/en/errors/charge_in_progress"},{"title":"code_expired","href":"/en/errors/code_expired"},{"title":"console_access_required","href":"/en/errors/console_access_required"},{"title":"event_not_resendable","href":"/en/errors/event_not_resendable"},{"title":"idempotency_conflict","href":"/en/errors/idempotency_conflict"},{"title":"insufficient_balance","href":"/en/errors/insufficient_balance"},{"title":"internal_error","href":"/en/errors/internal_error"},{"title":"invalid_api_key","href":"/en/errors/invalid_api_key"},{"title":"no_couriers_available","href":"/en/errors/no_couriers_available"},{"title":"not_cancellable","href":"/en/errors/not_cancellable"},{"title":"not_editable","href":"/en/errors/not_editable"},{"title":"not_found","href":"/en/errors/not_found"},{"title":"not_reactivatable","href":"/en/errors/not_reactivatable"},{"title":"not_refundable","href":"/en/errors/not_refundable"},{"title":"not_reschedulable","href":"/en/errors/not_reschedulable"},{"title":"not_retriable","href":"/en/errors/not_retriable"},{"title":"order_too_large","href":"/en/errors/order_too_large"},{"title":"out_of_service_area","href":"/en/errors/out_of_service_area"},{"title":"payout_account_not_ready","href":"/en/errors/payout_account_not_ready"},{"title":"pickup_point_pending","href":"/en/errors/pickup_point_pending"},{"title":"plan_ended","href":"/en/errors/plan_ended"},{"title":"plan_required","href":"/en/errors/plan_required"},{"title":"provider_unavailable","href":"/en/errors/provider_unavailable"},{"title":"quote_consumed","href":"/en/errors/quote_consumed"},{"title":"quote_expired","href":"/en/errors/quote_expired"},{"title":"rate_limited","href":"/en/errors/rate_limited"},{"title":"read_only_key","href":"/en/errors/read_only_key"},{"title":"refund_amount_too_large","href":"/en/errors/refund_amount_too_large"},{"title":"resend_limit_reached","href":"/en/errors/resend_limit_reached"},{"title":"same_day_below_minimum","href":"/en/errors/same_day_below_minimum"},{"title":"same_day_cap_exceeded","href":"/en/errors/same_day_cap_exceeded"},{"title":"test_webhook_limit_reached","href":"/en/errors/test_webhook_limit_reached"},{"title":"unsupported_country","href":"/en/errors/unsupported_country"},{"title":"validation_failed","href":"/en/errors/validation_failed"},{"title":"webhook_endpoint_not_configured","href":"/en/errors/webhook_endpoint_not_configured"}]},{"group":"Reference","pages":[{"group":"Balance","pages":[{"title":"Read your prepaid balance","deprecated":null,"version":null,"openapi":"/openapi/en.yaml get /v1/balance","href":"/api-reference/balance/read-your-prepaid-balance"},{"title":"Read a store's balance","deprecated":null,"version":null,"openapi":"/openapi/en.yaml get /v1/stores/{store_id}/balance","href":"/api-reference/balance/read-a-stores-balance"}]},{"group":"Account connection","pages":[{"title":"Ask a restaurant to connect its account","deprecated":null,"version":null,"openapi":"/openapi/en.yaml post /v1/connect_requests","href":"/api-reference/account-connection/ask-a-restaurant-to-connect-its-account"},{"title":"Exchange an approval for the store","deprecated":null,"version":null,"openapi":"/openapi/en.yaml post /v1/connections","href":"/api-reference/account-connection/exchange-an-approval-for-the-store"}]},{"group":"Deliveries","pages":[{"title":"List deliveries","deprecated":null,"version":null,"openapi":"/openapi/en.yaml get /v1/deliveries","href":"/api-reference/deliveries/list-deliveries"},{"title":"Create a delivery","deprecated":null,"version":null,"openapi":"/openapi/en.yaml post /v1/deliveries","href":"/api-reference/deliveries/create-a-delivery"},{"title":"Cancel a delivery","deprecated":null,"version":null,"openapi":"/openapi/en.yaml post /v1/deliveries/{delivery_id}/cancellations","href":"/api-reference/deliveries/cancel-a-delivery"},{"title":"Refund a delivery","deprecated":null,"version":null,"openapi":"/openapi/en.yaml post /v1/deliveries/{delivery_id}/refunds","href":"/api-reference/deliveries/refund-a-delivery"},{"title":"Retry a failed dispatch","deprecated":null,"version":null,"openapi":"/openapi/en.yaml post /v1/deliveries/{delivery_id}/retries","href":"/api-reference/deliveries/retry-a-failed-dispatch"},{"title":"Fetch a delivery","deprecated":null,"version":null,"openapi":"/openapi/en.yaml get /v1/deliveries/{id}","href":"/api-reference/deliveries/fetch-a-delivery"},{"title":"Update a delivery","deprecated":null,"version":null,"openapi":"/openapi/en.yaml patch /v1/deliveries/{id}","href":"/api-reference/deliveries/update-a-delivery"}]},{"group":"Events","pages":[{"title":"List your webhook events","deprecated":null,"version":null,"openapi":"/openapi/en.yaml get /v1/events","href":"/api-reference/events/list-your-webhook-events"},{"title":"Send a webhook event again","deprecated":null,"version":null,"openapi":"/openapi/en.yaml post /v1/events/{event_id}/resend","href":"/api-reference/events/send-a-webhook-event-again"},{"title":"Retrieve a webhook event","description":"One event, as the envelope your endpoint is sent. An event that is not\nyours, or belongs to the other mode, is `404 not_found`.\n","deprecated":null,"version":null,"openapi":"/openapi/en.yaml get /v1/events/{id}","href":"/api-reference/events/retrieve-a-webhook-event"},{"title":"Send a test webhook","deprecated":null,"version":null,"openapi":"/openapi/en.yaml post /v1/test_webhooks","href":"/api-reference/events/send-a-test-webhook"}]},{"group":"Ledger","pages":[{"title":"List your ledger entries","description":"Every movement on your balance, newest first, keyset-paginated. This is\nthe reconciliation surface: close a period by walking it rather than by\nadding up webhook events, so an event you missed, or one you had resent,\nchanges nothing about what you can rebuild.\n\n`amount_cents` is signed, credits positive and debits negative, which is\nwhat lets a page sum to the movement in your balance across it. Read the\ndirection off that sign and never off `type`.\n\n`type` says where a movement came from. The pair worth knowing is the\none a wasted trip produces:\n\n- `provider_charge` is the delivery fee billed for a late cancellation\n or a return trip, one fee per leg that was driven, less your own\n store markup. Negative, and tied to the order that caused it. **This\n amount changed on 2026-08-29**: it used to be what the wasted trip\n cost Listo, so expect larger values on the same orders from that date\n onward. The row itself is unchanged.\n- `provider_charge_reversal` is that charge credited back in full, when\n the cost turns out not to have been owed. Positive, and posted as its\n own row against the same `delivery_id` rather than as a reduction of\n the original charge, so what you were billed and what came back are\n both still readable. It can arrive weeks after the charge. Pair the\n two by `delivery_id` and expect equal and opposite amounts.\n\nA third value can appear on the same order and is a different amount\nunder a different heading:\n\n- `order_value_reimbursement` is the value of an order a courier\n collected that reached nobody, credited after we claim it. Positive,\n tied to the order it belongs to, and NOT paired with any debit on this\n ledger: the order's value never moved through your balance, so there\n is nothing to net it against. It is decided case by case and is not\n guaranteed, so never derive it from the order total or expect one per\n incident.\n- `listo_charge_correction` is a charge Listo made in error and gave\n back: a `provider_charge` that turned out not to be yours to pay.\n Positive, tied to the order it corrects, and posted as its own row\n beside the original charge, never as a reduction of it. Pair it with\n the charge by `delivery_id`; it can be less than the charge, and an\n order can carry more than one. It is decided case by case, so never\n derive it from a charge or expect one per charge.\n- `requote_adjustment` is the difference between the fee your order was\n charged and the fee the courier network booked for its trip, when the\n two are not the same. Signed: negative when the booked trip cost more\n than you were charged, positive when it cost less. Tied to the order,\n posted as its own row beside the order's own charge and never as a\n rewrite of it, and a retry of the same order trues it up to the trip\n finally booked rather than adding another. It is not paired with any\n other row, and it is uncommon.\n\nOne more is money you earn, and it is a credit:\n\n- `developer_share` is what you earn on a delivered trip of your own store,\n credited to you when the trip is delivered. Positive, and tied to the\n order it belongs to. A trip that is canceled or returned earns none.\n\nTwo more are a store's Plan Listo, paid from your balance:\n\n- `plan_charge` is one month of a store's plan, IVA included. Negative.\n A month paid by card writes no row, because it never touched the\n balance.\n- `plan_extra_charge` is the WhatsApp assistant's conversations past\n what a `full` store's plan includes, charged to you with that store's\n plan. Negative.\n\n`store_id` names the store a movement belongs to, on every row: the\nstore of the order, or the store whose plan was paid. It is `null` when\na movement belongs to no single store, such as a top-up or a withdrawal.\n\nThis vocabulary GROWS. New values can appear in any release, because v1\nchanges additively and a movement you cannot yet name is still money\nthat moved. So branch on the values you know and let the rest fall\nthrough: count an unfamiliar `type` toward the balance, show it, and do\nnot drop it or reject it. Rows you discard are the difference between\nyour books and `GET /v1/balance`.\n","deprecated":null,"version":null,"openapi":"/openapi/en.yaml get /v1/ledger","href":"/api-reference/ledger/list-your-ledger-entries"},{"title":"List a store's ledger entries","deprecated":null,"version":null,"openapi":"/openapi/en.yaml get /v1/stores/{store_id}/ledger","href":"/api-reference/ledger/list-a-stores-ledger-entries"}]},{"group":"Authentication","pages":[{"title":"Check that your API key works","deprecated":null,"version":null,"openapi":"/openapi/en.yaml get /v1/ping","href":"/api-reference/authentication/check-that-your-api-key-works"}]},{"group":"Quotes","pages":[{"title":"Price a delivery","deprecated":null,"version":null,"openapi":"/openapi/en.yaml post /v1/quotes","href":"/api-reference/quotes/price-a-delivery"}]},{"group":"Request logs","pages":[{"title":"List your request log","deprecated":null,"version":null,"openapi":"/openapi/en.yaml get /v1/request_logs","href":"/api-reference/request-logs/list-your-request-log"},{"title":"Retrieve a request log entry","deprecated":null,"version":null,"openapi":"/openapi/en.yaml get /v1/request_logs/{id}","href":"/api-reference/request-logs/retrieve-a-request-log-entry"}]},{"group":"Stores","pages":[{"title":"List your stores","deprecated":null,"version":null,"openapi":"/openapi/en.yaml get /v1/stores","href":"/api-reference/stores/list-your-stores"},{"title":"Create a store","deprecated":null,"version":null,"openapi":"/openapi/en.yaml post /v1/stores","href":"/api-reference/stores/create-a-store"},{"title":"Fetch a store","deprecated":null,"version":null,"openapi":"/openapi/en.yaml get /v1/stores/{id}","href":"/api-reference/stores/fetch-a-store"},{"title":"Update a store","deprecated":null,"version":null,"openapi":"/openapi/en.yaml patch /v1/stores/{id}","href":"/api-reference/stores/update-a-store"},{"title":"Invite a store owner","deprecated":null,"version":null,"openapi":"/openapi/en.yaml post /v1/stores/{store_id}/owner","href":"/api-reference/stores/invite-a-store-owner"},{"title":"Reactivate a store's plan","deprecated":null,"version":null,"openapi":"/openapi/en.yaml post /v1/stores/{store_id}/plan","href":"/api-reference/stores/reactivate-a-stores-plan"},{"title":"Cancel a store's plan","deprecated":null,"version":null,"openapi":"/openapi/en.yaml post /v1/stores/{store_id}/plan_cancellation","href":"/api-reference/stores/cancel-a-stores-plan"},{"title":"Undo a store's plan cancellation","deprecated":null,"version":null,"openapi":"/openapi/en.yaml delete /v1/stores/{store_id}/plan_cancellation","href":"/api-reference/stores/undo-a-stores-plan-cancellation"}]},{"group":"Card onboarding","pages":[{"title":"Start card onboarding for a store","deprecated":null,"version":null,"openapi":"/openapi/en.yaml post /v1/stores/{store_id}/stripe_onboarding","href":"/api-reference/card-onboarding/start-card-onboarding-for-a-store"},{"title":"Read a store's card readiness","deprecated":null,"version":null,"openapi":"/openapi/en.yaml get /v1/stores/{store_id}/stripe_status","href":"/api-reference/card-onboarding/read-a-stores-card-readiness"},{"title":"Start card onboarding for your company","deprecated":null,"version":null,"openapi":"/openapi/en.yaml post /v1/stripe_onboarding","href":"/api-reference/card-onboarding/start-card-onboarding-for-your-company"},{"title":"Read your company's card readiness","deprecated":null,"version":null,"openapi":"/openapi/en.yaml get /v1/stripe_status","href":"/api-reference/card-onboarding/read-your-companys-card-readiness"}]},{"group":"Webhook deliveries","pages":[{"title":"List webhook delivery attempts","deprecated":null,"version":null,"openapi":"/openapi/en.yaml get /v1/webhook_deliveries","href":"/api-reference/webhook-deliveries/list-webhook-delivery-attempts"}]},{"group":"Withdrawals","pages":[{"title":"List your withdrawals","deprecated":null,"version":null,"openapi":"/openapi/en.yaml get /v1/withdrawals","href":"/api-reference/withdrawals/list-your-withdrawals"},{"title":"Request a withdrawal","deprecated":null,"version":null,"openapi":"/openapi/en.yaml post /v1/withdrawals","href":"/api-reference/withdrawals/request-a-withdrawal"},{"title":"Fetch a withdrawal","deprecated":null,"version":null,"openapi":"/openapi/en.yaml get /v1/withdrawals/{id}","href":"/api-reference/withdrawals/fetch-a-withdrawal"}]},{"group":"Webhooks","pages":[{"title":"A delivery reached a new status","version":null,"deprecated":null,"openapi":"/openapi/en.yaml webhook delivery.status_changed","href":"/api-reference/webhooks/a-delivery-reached-a-new-status"},{"title":"A delivery changed without changing status","version":null,"deprecated":null,"openapi":"/openapi/en.yaml webhook delivery.updated","href":"/api-reference/webhooks/a-delivery-changed-without-changing-status"},{"title":"The courier moved","version":null,"deprecated":null,"openapi":"/openapi/en.yaml webhook delivery.courier_location","href":"/api-reference/webhooks/the-courier-moved"},{"title":"A withdrawal was settled","version":null,"deprecated":null,"openapi":"/openapi/en.yaml webhook withdrawal.updated","href":"/api-reference/webhooks/a-withdrawal-was-settled"},{"title":"A store changed","version":null,"deprecated":null,"openapi":"/openapi/en.yaml webhook store.updated","href":"/api-reference/webhooks/a-store-changed"},{"title":"A restaurant connected its existing account to you","version":null,"deprecated":null,"openapi":"/openapi/en.yaml webhook store.connected","href":"/api-reference/webhooks/a-restaurant-connected-its-existing-account-to-you"}]}]},{"group":"Concepts","pages":[{"title":"The money model","href":"/en/concepts/money"},{"title":"Where a delivery came from","href":"/en/concepts/delivery-origin"},{"title":"Test mode","href":"/en/concepts/test-mode"},{"title":"Signing","href":"/en/concepts/signing"},{"title":"Cash at the door","href":"/en/concepts/cash-at-the-door"}]},{"group":"Changelog","pages":[{"title":"Changelog","href":"/en/changelog"}]},{"group":"Legal","pages":[{"title":"Terms for Partners","url":"https://listo.delivery/terminos-partners","href":"/en/terms-for-partners"}]}]},{"language":"es","navbar":{"links":[{"href":"https://status.listo.delivery","label":"Estado del servicio"}]},"pages":[{"title":"es","href":"/es/api-reference/events/send-a-test-webhook"}]}]},"basePath":"","title":"Send a test webhook - Listo Partner API","buildId":"dpl_8LJbrAiZvr1K98WQNZXCyY5AvT34","deploymentId":"dpl_8LJbrAiZvr1K98WQNZXCyY5AvT34","dynamics":["c2aa737661","2b790eda92","b0f84f53ff","a9bb46feb3"],"chunks":["OpenApiReferenceProvider-i2a3QZ8E.js","utils-ChLwp8m0.js","cloneDeep-izs3Hzxb.js","_Uint8Array-BVIqJ90l.js","isObjectLike-C8vmzPEN.js","isArray-Dcu1dQ5t.js","utils-DRktVTDc.js","toString-BX-iyh8G.js","isSymbol-CSH9U2Gm.js","addUniqueKeysToSchema-CA2pEs4T.js","snippetPresets-ClQ6XrKD.js","style-to-object-BY3JEAdk.js","v4-DIgz8zy6.js","ApiExamples-Ct_Lv36y.js","isEqual-BfaiBbcl.js","usePlaygroundInputsStore-Cn2PYw9e.js","shallow-rkyymjXQ.js","getApiPlaygroundDisplay-BB9vkXtE.js","CodeSnippet-Bm5RU7m1.js","CodeSnippets-BgU9Deuz.js","Page-BUDYNlhG.js","getPastedJson-BD-6NNum.js","icon-8Z6tud2e.js","MethodPill-Tuzr4g3V.js","DuplicateIcon-0ceWFYhN.js","createIcon-FBXow_ST.js","DynamicMarkdown-CD8713Yy.js","SectionHeading-7zgzQbH-.js","axios-vUo_bRtp.js","Markdown-D7Ofw1oz.js","clsx-eKJ4rcii.js","lib-DuNMoZ05.js","lib-B8HbPgcC.js","html-void-elements-mCSPHezU.js","dist-CwjSCXIK.js","katex-YMM-FMeD.js","marked.esm-CZWythHk.js","AssistantPageLink-9EK5IAXV.js"]}