{
    "openapi": "3.0.0",
    "info": {
        "title": "Kapitano — Store Integration API",
        "description": "The **store integration API** (`/api/integration/v1/*`): how an external e-commerce platform\nhands delivery orders to Kapitano and hears what happens to them.\n\n---\n\n## What you can do to an order, and what you cannot\n\n| You want to | Use |\n|---|---|\n| send one | `POST /orders` |\n| read one back | `GET /orders/{uuid}`, or `GET /orders?external_order_id=` if you lost our uuid |\n| **change one** | `PATCH /orders/{uuid}` — partial, with timing rules |\n| **delete one** | **there is no `DELETE`.** Use `POST /orders/{uuid}/cancel` |\n| say the money moved | `POST /orders/{uuid}/payment` |\n\n### There is no delete, and there will not be\n\nIf you are looking for it: cancel *is* the delete, and it is better than one. Destroying an\norder would take three things with it —\n\n- the timeline a dispute is settled from;\n- the delivery-log entry proving we told you what happened;\n- and the release of the captain's reserved capacity, which is the dangerous one. A deleted\n  in-progress order leaves that captain's counter too high, and a counter that is too high\n  locks them out of **every** future assignment, silently, until somebody notices.\n\nCancel does everything a delete wants and keeps the evidence. If your own system deletes\norders, map that to a cancel here.\n\n---\n\n## 1. Required headers\n\nEvery request needs **all** of these. The first two are enforced globally by\n`CheckApiHeaderMiddleware`, **before** the token is even looked at — which is why a missing\nheader answers `401` and not `406`, and why a wrong secret and a missing header look alike\nuntil you read `MessageDebug`.\n\n| Header | Value |\n|---|---|\n| `Accept` | `application/json` — anything else answers `401` |\n| `Accept-Language` | `en` — sets the language of **our error messages**, not the customer's |\n| `Authorization` | `Bearer <access token>` |\n| `Idempotency-Key` | a UUID, on every `POST` |\n| `X-Kapitano-Signature` | `t=<unix>,v1=<hex>` — see below |\n\n> Send `Accept-Language: en` from a server. It decides the language of `Message` and\n> `MessageDebug`; Arabic there makes your own logs unsearchable. The **customer's** language\n> travels in the body, as `customer.locale`.\n\n---\n\n## 2. Signing a request\n\n```\nsigned_payload = \"{t}.\" + <raw request body>\nv1             = HMAC_SHA256(signed_payload, <your signing secret>)   // lowercase hex\nheader         = X-Kapitano-Signature: t={t},v1={v1}\n```\n\n`t` is a Unix timestamp in seconds. The body is **the exact bytes you send** — re-encoding\nthe JSON after signing changes key order or spacing and breaks the signature, which is the\nsingle most common integration fault.\n\n**Test vector** — run this and you must get the same hash:\n\n```\nsigning_secret : whsec_sample_do_not_use_in_production\nt              : 1758182400\nbody           : {\"external_order_id\":\"SO-77120\"}\nv1             : 25988882fa0479d9a3e402ecac3d892d9a177bfc4fbdb018e0be0330d86d10b1\n```\n\nRules: the timestamp must be within **300 seconds** of ours, and each signature is accepted\n**once**. A `GET` has an empty body, so it signs `\"{t}.\"` and nothing more.\n\n---\n\n## 3. Retrying\n\nA retry needs a **new signature** (new `t`) and the **same** `Idempotency-Key`. Re-sending\nidentical headers is refused as `signature_replayed` before the idempotency check is ever\nreached — the two protect different things:\n\n- the signature stops a captured request being replayed;\n- the key stops a genuine retry becoming a second delivery.\n\nRetry on `429`, `500`, `502`, `503`, `504` and network errors. Do **not** retry other `4xx`:\nthey are faults in the request and will not change.\n\n---\n\n## 4. Response envelope\n\nEvery response, success or failure, is the same shape:\n\n```json\n{ \"Model\": {}, \"Status\": true, \"Message\": null, \"MessageDebug\": null,\n  \"Total\": 0, \"Page\": 0, \"Records\": 0 }\n```\n\n`MessageDebug` carries the machine-readable reason on failure. **Branch on its key**, not on\nthe message text — the keys are the contract and are listed per endpoint below.\n\n---\n\n## 5. Webhooks we send you\n\nGive us one URL and a secret, and we `POST` every lifecycle change to it, signed with the\n**same** scheme above (using your *webhook* secret, not your signing secret — they are\ndeliberately different, so a leak in one direction cannot forge the other).\n\nHeaders: `X-Kapitano-Event`, `X-Kapitano-Event-Id`, `X-Kapitano-Delivery-Attempt`,\n`X-Kapitano-Signature`.\n\nBesides the lifecycle events there is **`order.updated`**, sent when something you can see\nchanges without the order moving — a corrected ETA, a payment that settled or was refunded.\nEvery payload carries the **whole order**, so treat any event as \"overwrite your copy\" rather\nthan working out which field moved. A change *you* made is never sent back to you.\n\nThree rules your receiver must follow:\n\n1. **Discard anything not newer.** Each payload carries `sequence`, which only ever\n   increases per order. Retries can arrive out of order; keep the highest you have processed\n   and drop the rest. Do not order by `occurred_at` — clocks drift, ids do not.\n2. **Expect duplicates.** `event_id` is unique per event. Store it and ignore repeats.\n3. **Answer `2xx` within 15 seconds**, then process in the background. Anything else counts\n   as a failure.\n\nWe retry six times over about two and a half hours (10s, 1m, 5m, 15m, 1h, 1h) and then stop,\nmarking the event *dropped*. The order's state is still readable at any time via\n`GET /orders/{uuid}`, and we can re-send a dropped event on request.\n\nThe body is the `StoreWebhookPayload` schema, at the bottom of this page under **Schemas**.\nThere is no endpoint here to call — it documents what arrives at yours.",
        "version": "1.0.0"
    },
    "servers": [
        {
            "url": "https://captain.kapitano.shop",
            "description": "Production API"
        },
        {
            "url": "http://127.0.0.1:8000",
            "description": "Local — php artisan serve"
        },
        {
            "url": "http://localhost/kapitano_logistic",
            "description": "Local — XAMPP (htdocs)"
        }
    ],
    "paths": {
        "/api/integration/v1/health": {
            "get": {
                "tags": [
                    "Store — Connectivity"
                ],
                "summary": "Check the credentials, the signature and the clock",
                "description": "Point your client here first. Reaching it proves the whole chain at once — both required\nheaders, a live token, an allowed source address and a correct signature — which is far\ncheaper to discover here than on your first real order.\n\n`clock_skew_seconds` is our time minus the `t` you just signed with. **Positive means your\nclock is behind.** Anything beyond ±30s is worth fixing now: past 300s every request\nstarts failing as `signature_expired`.\n\nAlso usable as a liveness probe. `accepting_orders: false` means intake is paused for\nmaintenance and `POST /orders` is answering 503 — your retries will pick them up.",
                "operationId": "storeHealth",
                "parameters": [
                    {
                        "name": "X-Kapitano-Signature",
                        "in": "header",
                        "description": "A GET has no body, so it signs \"{t}.\" — see the API description.",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "example": "t=1758182400,v1=25988882fa0479d9…"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Everything checks out.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "properties": {
                                        "Model": {
                                            "properties": {
                                                "client": {
                                                    "type": "string",
                                                    "example": "Kapitano Marketplace"
                                                },
                                                "environment": {
                                                    "type": "string",
                                                    "example": "production"
                                                },
                                                "server_time": {
                                                    "type": "string",
                                                    "format": "date-time"
                                                },
                                                "clock_skew_seconds": {
                                                    "description": "Our time minus your signed timestamp. Positive = your clock is behind.",
                                                    "type": "integer",
                                                    "example": 2,
                                                    "nullable": true
                                                },
                                                "signature_tolerance_seconds": {
                                                    "type": "integer",
                                                    "example": 300
                                                },
                                                "accepting_orders": {
                                                    "type": "boolean",
                                                    "example": true
                                                }
                                            },
                                            "type": "object"
                                        },
                                        "Status": {
                                            "type": "boolean",
                                            "example": true
                                        }
                                    },
                                    "type": "object"
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "Headers, token or signature.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/StoreErrorSignature"
                                }
                            }
                        }
                    },
                    "403": {
                        "description": "Address not allowed, client paused, or token lacks orders:read.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/StoreErrorForbidden"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Rate limit exceeded. Wait for Retry-After."
                    }
                },
                "security": [
                    {
                        "storeAuth": []
                    }
                ]
            }
        },
        "/api/integration/v1/orders": {
            "get": {
                "tags": [
                    "Store — Orders"
                ],
                "summary": "Find an order by your own reference",
                "description": "Recovery for a lost uuid. The reference travels as a query parameter rather than in the path so it stays out of access logs and browser history.",
                "operationId": "storeOrderLookup",
                "parameters": [
                    {
                        "name": "external_order_id",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string",
                            "maxLength": 64
                        },
                        "example": "SO-77120"
                    },
                    {
                        "name": "X-Kapitano-Signature",
                        "in": "header",
                        "required": true,
                        "schema": {
                            "type": "string"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "The order.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "properties": {
                                        "Model": {
                                            "$ref": "#/components/schemas/StoreOrderDetail"
                                        },
                                        "Status": {
                                            "type": "boolean",
                                            "example": true
                                        }
                                    },
                                    "type": "object"
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "Headers, token or signature.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/StoreErrorSignature"
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "No order of yours carries that reference.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/StoreErrorNotFound"
                                }
                            }
                        }
                    },
                    "422": {
                        "description": "The reference is missing.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/StoreErrorValidation"
                                }
                            }
                        }
                    }
                },
                "security": [
                    {
                        "storeAuth": []
                    }
                ]
            },
            "post": {
                "tags": [
                    "Store — Orders"
                ],
                "summary": "Hand us an order for delivery",
                "description": "Send this **the moment the order is ready to be collected**, not when the customer places\nit: it enters the dispatcher's queue on arrival, and sending it early means a captain\nwaiting at your counter. Use `pickup.ready_at` if you want to send it slightly ahead.\n\n**`201`** when it is new. **`200`** when the same `Idempotency-Key` and the same body\narrive again — the original response is returned verbatim with an `Idempotency-Replayed:\ntrue` header, and nothing is written. A retry is not an error.\n\n### Five fields are required here that you might expect to be optional\n\nEach one prevents a specific, silent failure:\n\n| Field | Without it |\n|---|---|\n| `pickup.lat` / `pickup.lng` | the order can **never** be assigned — the captain ranking has no point to measure from, so it would sit stranded forever. Refused at the door instead |\n| `dropoff.lat` / `dropoff.lng` | no ETA and no arrival alert |\n| `customer.phone` | the captain cannot call |\n| `payment.status` | we would default to *cash on delivery* and tell the captain to collect money a prepaid customer has already paid |\n| `items` (≥ 1) | the captain's item-count check at pickup silently stops working |\n\n`customer.external_id` is required for a different reason: it is the key we write the\ncaptain's captured address details back under. It costs nothing now and cannot be\nretrofitted later.",
                "operationId": "storeOrderCreate",
                "parameters": [
                    {
                        "name": "Idempotency-Key",
                        "in": "header",
                        "description": "One per order, reused on every retry of that order.",
                        "required": true,
                        "schema": {
                            "type": "string",
                            "maxLength": 128
                        },
                        "example": "3f6c1b9e-8a2d-4c77-9f10-6b2e5d3a7c41"
                    },
                    {
                        "name": "X-Kapitano-Signature",
                        "in": "header",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "example": "t=1758182400,v1=25988882fa0479d9…"
                    }
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "required": [
                                    "external_order_id",
                                    "external_order_number",
                                    "customer",
                                    "pickup",
                                    "dropoff",
                                    "payment",
                                    "items"
                                ],
                                "properties": {
                                    "external_order_id": {
                                        "description": "Your reference. The handle for every later call. Must be unique and never reused.",
                                        "type": "string",
                                        "example": "SO-77120",
                                        "maxLength": 64
                                    },
                                    "external_order_number": {
                                        "description": "The number your customer sees; shown to the captain.",
                                        "type": "string",
                                        "example": "77120",
                                        "maxLength": 64
                                    },
                                    "customer": {
                                        "required": [
                                            "external_id",
                                            "name",
                                            "phone"
                                        ],
                                        "properties": {
                                            "external_id": {
                                                "description": "Stable customer id in your system.",
                                                "type": "string",
                                                "example": "CUST-4417",
                                                "maxLength": 64
                                            },
                                            "name": {
                                                "type": "string",
                                                "example": "عبدالله الحربي",
                                                "maxLength": 255
                                            },
                                            "phone": {
                                                "description": "E.164. A number without a country code is left as sent and fails validation rather than being guessed at.",
                                                "type": "string",
                                                "example": "+966501234567",
                                                "maxLength": 30
                                            },
                                            "locale": {
                                                "description": "The customer's language, not yours.",
                                                "type": "string",
                                                "nullable": true,
                                                "enum": [
                                                    "ar",
                                                    "en"
                                                ]
                                            },
                                            "note": {
                                                "description": "Shown to the captain.",
                                                "type": "string",
                                                "nullable": true,
                                                "maxLength": 1000
                                            }
                                        },
                                        "type": "object"
                                    },
                                    "pickup": {
                                        "required": [
                                            "branch_ref",
                                            "name",
                                            "address",
                                            "lat",
                                            "lng"
                                        ],
                                        "properties": {
                                            "branch_ref": {
                                                "type": "string",
                                                "example": "BR-RUH-07",
                                                "maxLength": 64
                                            },
                                            "name": {
                                                "type": "string",
                                                "example": "فرع طريق الملك فهد",
                                                "maxLength": 255
                                            },
                                            "address": {
                                                "type": "string",
                                                "maxLength": 255
                                            },
                                            "lat": {
                                                "type": "number",
                                                "example": 24.7135999999999995679900166578590869903564453125,
                                                "maximum": 90,
                                                "minimum": -90
                                            },
                                            "lng": {
                                                "type": "number",
                                                "example": 46.67530000000000001136868377216160297393798828125,
                                                "maximum": 180,
                                                "minimum": -180
                                            },
                                            "ready_at": {
                                                "description": "When the order will actually be bagged.",
                                                "type": "string",
                                                "format": "date-time",
                                                "nullable": true
                                            }
                                        },
                                        "type": "object"
                                    },
                                    "dropoff": {
                                        "required": [
                                            "address",
                                            "lat",
                                            "lng"
                                        ],
                                        "properties": {
                                            "address": {
                                                "type": "string",
                                                "maxLength": 255
                                            },
                                            "lat": {
                                                "type": "number",
                                                "example": 24.751999999999998891553332214243710041046142578125,
                                                "maximum": 90,
                                                "minimum": -90
                                            },
                                            "lng": {
                                                "type": "number",
                                                "example": 46.6580000000000012505552149377763271331787109375,
                                                "maximum": 180,
                                                "minimum": -180
                                            },
                                            "address_ref": {
                                                "description": "The address id in your customer's address book.",
                                                "type": "string",
                                                "nullable": true,
                                                "maxLength": 64
                                            },
                                            "details": {
                                                "properties": {
                                                    "building": {
                                                        "type": "string",
                                                        "nullable": true,
                                                        "maxLength": 120
                                                    },
                                                    "floor": {
                                                        "type": "string",
                                                        "nullable": true,
                                                        "maxLength": 120
                                                    },
                                                    "apartment": {
                                                        "type": "string",
                                                        "nullable": true,
                                                        "maxLength": 120
                                                    },
                                                    "landmark": {
                                                        "type": "string",
                                                        "nullable": true,
                                                        "maxLength": 120
                                                    }
                                                },
                                                "type": "object",
                                                "nullable": true
                                            }
                                        },
                                        "type": "object"
                                    },
                                    "payment": {
                                        "required": [
                                            "method",
                                            "status"
                                        ],
                                        "properties": {
                                            "method": {
                                                "type": "string",
                                                "enum": [
                                                    "cash_on_delivery",
                                                    "prepaid"
                                                ]
                                            },
                                            "status": {
                                                "description": "Whether the money has actually moved. Required — see the description.",
                                                "type": "string",
                                                "enum": [
                                                    "paid",
                                                    "unpaid",
                                                    "refunded"
                                                ]
                                            },
                                            "amount_to_collect": {
                                                "description": "Required for cash_on_delivery; ignored for prepaid.",
                                                "type": "number",
                                                "example": 148,
                                                "nullable": true,
                                                "minimum": 0
                                            },
                                            "reference": {
                                                "type": "string",
                                                "nullable": true,
                                                "maxLength": 120
                                            }
                                        },
                                        "type": "object"
                                    },
                                    "currency": {
                                        "description": "Defaults to SAR when omitted.",
                                        "type": "string",
                                        "example": "SAR",
                                        "nullable": true,
                                        "maxLength": 3
                                    },
                                    "delivery_fee": {
                                        "description": "Your number. Defaults to 0 when omitted.",
                                        "type": "number",
                                        "example": 15,
                                        "nullable": true,
                                        "minimum": 0
                                    },
                                    "promised_at": {
                                        "description": "The delivery promise you gave the customer. Without it we cannot check that stacking this order onto a captain's route would still meet it, so every stack is accepted.",
                                        "type": "string",
                                        "format": "date-time",
                                        "nullable": true
                                    },
                                    "note": {
                                        "description": "Operational note for our team; never shown to the customer.",
                                        "type": "string",
                                        "nullable": true,
                                        "maxLength": 1000
                                    },
                                    "items": {
                                        "type": "array",
                                        "items": {
                                            "required": [
                                                "name",
                                                "quantity"
                                            ],
                                            "properties": {
                                                "name": {
                                                    "type": "string",
                                                    "maxLength": 255
                                                },
                                                "quantity": {
                                                    "type": "integer",
                                                    "maximum": 999,
                                                    "minimum": 1
                                                },
                                                "unit_price": {
                                                    "type": "number",
                                                    "nullable": true,
                                                    "minimum": 0
                                                },
                                                "sku": {
                                                    "type": "string",
                                                    "nullable": true,
                                                    "maxLength": 255
                                                },
                                                "note": {
                                                    "type": "string",
                                                    "nullable": true,
                                                    "maxLength": 255
                                                }
                                            },
                                            "type": "object"
                                        },
                                        "maxItems": 50,
                                        "minItems": 1
                                    }
                                },
                                "type": "object"
                            },
                            "example": {
                                "external_order_id": "SO-77120",
                                "external_order_number": "77120",
                                "customer": {
                                    "external_id": "CUST-4417",
                                    "name": "عبدالله الحربي",
                                    "phone": "+966501234567",
                                    "locale": "ar",
                                    "note": "الرجاء الاتصال قبل الوصول"
                                },
                                "pickup": {
                                    "branch_ref": "BR-RUH-07",
                                    "name": "فرع طريق الملك فهد",
                                    "address": "طريق الملك فهد، حي العليا، الرياض",
                                    "lat": 24.7135999999999995679900166578590869903564453125,
                                    "lng": 46.67530000000000001136868377216160297393798828125,
                                    "ready_at": "2026-09-18T11:20:00+03:00"
                                },
                                "dropoff": {
                                    "address": "شارع التخصصي، حي المروج، الرياض",
                                    "lat": 24.751999999999998891553332214243710041046142578125,
                                    "lng": 46.6580000000000012505552149377763271331787109375,
                                    "address_ref": "ADDR-9981",
                                    "details": {
                                        "building": "برج السلام",
                                        "floor": "4",
                                        "apartment": "402"
                                    }
                                },
                                "payment": {
                                    "method": "cash_on_delivery",
                                    "status": "unpaid",
                                    "amount_to_collect": 148
                                },
                                "currency": "SAR",
                                "delivery_fee": 15,
                                "promised_at": "2026-09-18T12:15:00+03:00",
                                "items": [
                                    {
                                        "name": "برجر لحم",
                                        "quantity": 2,
                                        "unit_price": 45,
                                        "sku": "BRG-01"
                                    },
                                    {
                                        "name": "بطاطس كبير",
                                        "quantity": 1,
                                        "unit_price": 18
                                    }
                                ]
                            }
                        }
                    }
                },
                "responses": {
                    "201": {
                        "description": "Accepted. Store the uuid.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "properties": {
                                        "Model": {
                                            "$ref": "#/components/schemas/StoreOrderSummary"
                                        },
                                        "Status": {
                                            "type": "boolean",
                                            "example": true
                                        }
                                    },
                                    "type": "object"
                                }
                            }
                        }
                    },
                    "200": {
                        "description": "Idempotent replay — the same key and body as before. Nothing was written; the original response is returned.",
                        "headers": {
                            "Idempotency-Replayed": {
                                "description": "Present and \"true\" on a replay.",
                                "schema": {
                                    "type": "string",
                                    "example": "true"
                                }
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "properties": {
                                        "Model": {
                                            "$ref": "#/components/schemas/StoreOrderSummary"
                                        },
                                        "Status": {
                                            "type": "boolean",
                                            "example": true
                                        }
                                    },
                                    "type": "object"
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "Headers, token or signature.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/StoreErrorSignature"
                                }
                            }
                        }
                    },
                    "403": {
                        "description": "Token lacks orders:write, address not allowed, or client paused.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/StoreErrorForbidden"
                                }
                            }
                        }
                    },
                    "409": {
                        "description": "The reference already exists, or the key was reused with a different body.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/StoreErrorConflict"
                                }
                            }
                        }
                    },
                    "422": {
                        "description": "Validation failed, or the Idempotency-Key is missing.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/StoreErrorValidation"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Rate limit exceeded."
                    },
                    "503": {
                        "description": "Intake paused, or the replay check is unavailable. Retry with the same key.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/StoreErrorUnavailable"
                                }
                            }
                        }
                    }
                },
                "security": [
                    {
                        "storeAuth": []
                    }
                ]
            }
        },
        "/api/integration/v1/orders/{order}": {
            "get": {
                "tags": [
                    "Store — Orders"
                ],
                "summary": "Read one order back",
                "description": "Your repair path when a webhook was lost, and the way to confirm a state you are unsure\nof. **Not a substitute for the webhooks** — polling this on a timer will meet the rate\nlimit, and the events carry the same body anyway.\n\nAn order belonging to another client answers **404**, not 403: a 403 would confirm it\nexists to anyone guessing references.",
                "operationId": "storeOrderShow",
                "parameters": [
                    {
                        "name": "order",
                        "in": "path",
                        "description": "Our uuid, from the create response.",
                        "required": true,
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    {
                        "name": "X-Kapitano-Signature",
                        "in": "header",
                        "required": true,
                        "schema": {
                            "type": "string"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "The order.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "properties": {
                                        "Model": {
                                            "$ref": "#/components/schemas/StoreOrderDetail"
                                        },
                                        "Status": {
                                            "type": "boolean",
                                            "example": true
                                        }
                                    },
                                    "type": "object"
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "Headers, token or signature.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/StoreErrorSignature"
                                }
                            }
                        }
                    },
                    "403": {
                        "description": "Token lacks orders:read.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/StoreErrorForbidden"
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "No such order for you.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/StoreErrorNotFound"
                                }
                            }
                        }
                    }
                },
                "security": [
                    {
                        "storeAuth": []
                    }
                ]
            },
            "patch": {
                "tags": [
                    "Store — Orders"
                ],
                "summary": "Change an order you have already sent",
                "description": "A **partial** edit. Anything you leave out is left alone; anything you send as `null` is\ncleared. Those are different instructions, and this endpoint keeps them apart — so do not\nsend a whole order back to change one field.\n\n---\n\n## What can still be changed, and until when\n\nAn edit is refused once the thing it would change **has already been acted on in the\nphysical world** — not when it becomes inconvenient, but when it becomes a lie.\n\n| You are changing | Allowed until | Refusal after that |\n|---|---|---|\n| `customer.*`, `note` | the order ends | — |\n| `pickup.*` | `assigned` | `409 pickup_locked` |\n| `items`, `payment.amount_to_collect`, `currency`, `delivery_fee` | `picked_up` | `409 order_already_collected` |\n| `dropoff.*` | `on_the_way` | `409 order_in_transit` |\n| `promised_at` | `delivered` | `409 order_not_editable` |\n\nOnce the order is `delivered`, `delivery_failed` or `cancelled`, **nothing** can change:\n`409 order_not_editable`.\n\nWhy each one stops where it does:\n\n- **Pickup** locks at `assigned` because the captain was *chosen* by their distance to\n  that branch. Moving it afterwards does not move them; it silently makes the assignment\n  wrong.\n- **Items and money** lock at `picked_up`. They are carrying the goods and were shown the\n  amount at the door.\n- **Dropoff** locks at `on_the_way` because somebody is driving to the old address. If\n  the customer moves after that, **cancel and send a new order** — we do not re-target a\n  delivery in flight.\n\n---\n\n## What can never be changed\n\nThese answer `422` naming the field, rather than being quietly ignored:\n\n| Field | Do this instead |\n|---|---|\n| `payment.method` | Cancel and send a new order. Switching cash to prepaid mid-flight means a captain collects money already paid, or fails to collect money owed |\n| `external_order_id` | Nothing — it is the key the duplicate guard is built on |\n| `status`, `driver_uuid` | Nothing. Where an order has got to is ours to say |\n\n---\n\n## Two details worth knowing\n\n**`items` is a replacement, not a merge.** Send the complete basket. A partial list would\nbe ambiguous about whether the lines you left out were removed or simply not mentioned.\n\n**You will not get a webhook for your own edit.** `order.updated` fires for these fields,\nbut not back at the client that asked for the change — echoing your own change at you is\nnoise you would then have to deduplicate.\n\n**There is no `DELETE`.** [Cancel](#operation/storeOrderCancel) is the delete: it frees\nthe captain, keeps the timeline a dispute needs, and leaves your delivery log pointing at\nsomething. If your system deletes orders, map that to a cancel.",
                "operationId": "storeOrderUpdate",
                "parameters": [
                    {
                        "name": "order",
                        "in": "path",
                        "description": "Our uuid, from the create response.",
                        "required": true,
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    {
                        "name": "Idempotency-Key",
                        "in": "header",
                        "required": true,
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    {
                        "name": "X-Kapitano-Signature",
                        "in": "header",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "example": "t=1758182400,v1=25988882fa0479d9…"
                    }
                ],
                "requestBody": {
                    "description": "Only the parts you are changing.",
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "properties": {
                                    "customer": {
                                        "properties": {
                                            "name": {
                                                "type": "string",
                                                "maxLength": 255
                                            },
                                            "phone": {
                                                "type": "string",
                                                "maxLength": 30
                                            },
                                            "note": {
                                                "description": "null clears it.",
                                                "type": "string",
                                                "nullable": true,
                                                "maxLength": 1000
                                            }
                                        },
                                        "type": "object"
                                    },
                                    "note": {
                                        "type": "string",
                                        "nullable": true,
                                        "maxLength": 1000
                                    },
                                    "pickup": {
                                        "description": "Send it whole — address and both coordinates are required together.",
                                        "properties": {
                                            "branch_ref": {
                                                "type": "string",
                                                "maxLength": 64
                                            },
                                            "name": {
                                                "type": "string",
                                                "maxLength": 255
                                            },
                                            "address": {
                                                "type": "string",
                                                "maxLength": 255
                                            },
                                            "lat": {
                                                "type": "number",
                                                "format": "float"
                                            },
                                            "lng": {
                                                "type": "number",
                                                "format": "float"
                                            },
                                            "ready_at": {
                                                "type": "string",
                                                "format": "date-time",
                                                "nullable": true
                                            }
                                        },
                                        "type": "object"
                                    },
                                    "dropoff": {
                                        "description": "Coordinates are both-or-neither: one without the other is half a point, which reads as a location and is not one.",
                                        "properties": {
                                            "address": {
                                                "type": "string",
                                                "maxLength": 255
                                            },
                                            "lat": {
                                                "type": "number",
                                                "format": "float"
                                            },
                                            "lng": {
                                                "type": "number",
                                                "format": "float"
                                            },
                                            "address_ref": {
                                                "type": "string",
                                                "nullable": true,
                                                "maxLength": 64
                                            }
                                        },
                                        "type": "object"
                                    },
                                    "payment": {
                                        "properties": {
                                            "amount_to_collect": {
                                                "type": "number",
                                                "format": "float",
                                                "minimum": 0
                                            },
                                            "reference": {
                                                "type": "string",
                                                "nullable": true,
                                                "maxLength": 120
                                            }
                                        },
                                        "type": "object"
                                    },
                                    "currency": {
                                        "type": "string",
                                        "maxLength": 3
                                    },
                                    "delivery_fee": {
                                        "type": "number",
                                        "format": "float",
                                        "minimum": 0
                                    },
                                    "promised_at": {
                                        "type": "string",
                                        "format": "date-time",
                                        "nullable": true
                                    },
                                    "items": {
                                        "description": "The COMPLETE basket. Replaces what is there.",
                                        "type": "array",
                                        "items": {
                                            "properties": {
                                                "name": {
                                                    "type": "string"
                                                },
                                                "quantity": {
                                                    "type": "integer",
                                                    "minimum": 1
                                                },
                                                "unit_price": {
                                                    "type": "number",
                                                    "nullable": true
                                                },
                                                "sku": {
                                                    "type": "string",
                                                    "nullable": true
                                                }
                                            },
                                            "type": "object"
                                        }
                                    }
                                },
                                "type": "object"
                            },
                            "example": {
                                "customer": {
                                    "phone": "966500000123"
                                },
                                "dropoff": {
                                    "address": "Al Murooj, Building 12",
                                    "lat": 24.751999999999998891553332214243710041046142578125,
                                    "lng": 46.6580000000000012505552149377763271331787109375
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Updated. The whole order comes back, in the same shape every webhook carries.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/StoreOrderDetail"
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "Headers, token or signature.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/StoreErrorSignature"
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "No such order of yours. Never 403 — that would confirm it exists.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/StoreErrorNotFound"
                                }
                            }
                        }
                    },
                    "409": {
                        "description": "Too late: `order_in_transit`, `pickup_locked`, `order_already_collected` or `order_not_editable`.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/StoreErrorConflict"
                                }
                            }
                        }
                    },
                    "422": {
                        "description": "A field that is never editable, a half coordinate, or `nothing_to_update`.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/StoreErrorValidation"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Rate limit exceeded."
                    }
                },
                "security": [
                    {
                        "storeAuth": []
                    }
                ]
            }
        },
        "/api/integration/v1/orders/{order}/cancel": {
            "post": {
                "tags": [
                    "Store — Orders"
                ],
                "summary": "Call an order off — this is the delete",
                "description": "**Looking for `DELETE /orders/{uuid}`? This is it.** There is no delete endpoint, and\ncancel is better than one: it frees the captain, keeps the timeline a dispute is settled\nfrom, and leaves your delivery log pointing at something. See the API description for why\na destroyed order is worse than a cancelled one. If your system deletes orders, map that\nto this call.\n\n**Send it immediately.** Every minute of delay is a captain driving to a branch that\nhas nothing for them.\n\nAccepted from any stage that is not already finished — including after the captain has\ncollected the goods. Refusing to *record* a cancellation would not undo the customer's\ndecision, it would only leave the order lying about its state; recovering goods from a\ncar is an operations conversation, and we will start it.\n\nA `delivered`, `delivery_failed` or already-cancelled order answers **422**.\n\nCancelling an assigned order frees the captain immediately, and you receive an\n`order.cancelled` webhook.",
                "operationId": "storeOrderCancel",
                "parameters": [
                    {
                        "name": "order",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    {
                        "name": "Idempotency-Key",
                        "in": "header",
                        "required": true,
                        "schema": {
                            "type": "string",
                            "maxLength": 128
                        }
                    },
                    {
                        "name": "X-Kapitano-Signature",
                        "in": "header",
                        "required": true,
                        "schema": {
                            "type": "string"
                        }
                    }
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "required": [
                                    "reason"
                                ],
                                "properties": {
                                    "reason": {
                                        "description": "Read by the dispatcher when the captain is already at the branch. Required.",
                                        "type": "string",
                                        "example": "Customer changed their mind",
                                        "maxLength": 255
                                    },
                                    "reason_code": {
                                        "description": "Your own vocabulary, kept on the timeline so both sides can reconcile without parsing free text.",
                                        "type": "string",
                                        "example": "CUSTOMER_CANCELLED",
                                        "nullable": true,
                                        "maxLength": 64
                                    }
                                },
                                "type": "object"
                            },
                            "example": {
                                "reason": "Customer changed their mind",
                                "reason_code": "CUSTOMER_CANCELLED"
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Cancelled.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "properties": {
                                        "Model": {
                                            "$ref": "#/components/schemas/StoreOrderDetail"
                                        },
                                        "Status": {
                                            "type": "boolean",
                                            "example": true
                                        }
                                    },
                                    "type": "object"
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "Headers, token or signature.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/StoreErrorSignature"
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "No such order for you.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/StoreErrorNotFound"
                                }
                            }
                        }
                    },
                    "422": {
                        "description": "No reason given, or the order has already finished.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/StoreErrorValidation"
                                }
                            }
                        }
                    }
                },
                "security": [
                    {
                        "storeAuth": []
                    }
                ]
            }
        },
        "/api/integration/v1/orders/{order}/payment": {
            "post": {
                "tags": [
                    "Store — Orders"
                ],
                "summary": "Tell us the money moved — or came back",
                "description": "**A refund is the case this exists for.** The payment *method* cannot express one, and a\ncaptain must not hand goods over on an order the customer has already been refunded for.\n\nSetting `paid` stamps when we learned it; `refunded` clears that stamp, because a refund\nis not a verified payment.",
                "operationId": "storeOrderPayment",
                "parameters": [
                    {
                        "name": "order",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    {
                        "name": "Idempotency-Key",
                        "in": "header",
                        "required": true,
                        "schema": {
                            "type": "string",
                            "maxLength": 128
                        }
                    },
                    {
                        "name": "X-Kapitano-Signature",
                        "in": "header",
                        "required": true,
                        "schema": {
                            "type": "string"
                        }
                    }
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "required": [
                                    "status"
                                ],
                                "properties": {
                                    "status": {
                                        "type": "string",
                                        "example": "refunded",
                                        "enum": [
                                            "paid",
                                            "unpaid",
                                            "refunded"
                                        ]
                                    },
                                    "reference": {
                                        "type": "string",
                                        "example": "RFND-99213",
                                        "nullable": true,
                                        "maxLength": 120
                                    },
                                    "paid_at": {
                                        "type": "string",
                                        "format": "date-time",
                                        "nullable": true
                                    }
                                },
                                "type": "object"
                            },
                            "example": {
                                "status": "paid",
                                "reference": "PAY-99213",
                                "paid_at": "2026-09-18T11:10:00+03:00"
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Recorded.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "properties": {
                                        "Model": {
                                            "$ref": "#/components/schemas/StoreOrderDetail"
                                        },
                                        "Status": {
                                            "type": "boolean",
                                            "example": true
                                        }
                                    },
                                    "type": "object"
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "Headers, token or signature.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/StoreErrorSignature"
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "No such order for you.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/StoreErrorNotFound"
                                }
                            }
                        }
                    },
                    "422": {
                        "description": "Unknown status.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/StoreErrorValidation"
                                }
                            }
                        }
                    }
                },
                "security": [
                    {
                        "storeAuth": []
                    }
                ]
            }
        }
    },
    "components": {
        "schemas": {
            "StoreErrorConflict": {
                "description": "409 — the order or the key has been seen before. Not retryable; read the order back instead.",
                "properties": {
                    "Model": {
                        "description": "409 — we have seen this order, or this key, before.",
                        "example": null,
                        "nullable": true
                    },
                    "Status": {
                        "type": "boolean",
                        "example": false
                    },
                    "Message": {
                        "type": "string",
                        "example": "An order with the reference SO-77120 has already been received."
                    },
                    "MessageDebug": {
                        "type": "object",
                        "example": {
                            "duplicate_external_order": [
                                "SO-77120"
                            ]
                        }
                    }
                },
                "type": "object"
            },
            "StoreErrorForbidden": {
                "description": "403 — the credential is valid but not allowed to do this. Keys: `missing_ability`, `ip_not_allowed`, `client_inactive`.",
                "properties": {
                    "Model": {
                        "description": "403 — the credential is real, but not allowed to do this.",
                        "example": null,
                        "nullable": true
                    },
                    "Status": {
                        "type": "boolean",
                        "example": false
                    },
                    "Message": {
                        "type": "string",
                        "example": "This token is not allowed to orders:write."
                    },
                    "MessageDebug": {
                        "type": "object",
                        "example": {
                            "missing_ability": [
                                "orders:write"
                            ]
                        }
                    }
                },
                "type": "object"
            },
            "StoreErrorNotFound": {
                "description": "404 — no such order **for you**. An order belonging to another client answers this too, rather than 403, so a reference cannot be confirmed by guessing.",
                "properties": {
                    "Model": {
                        "description": "404 — and deliberately also the answer for somebody else's order.",
                        "example": null,
                        "nullable": true
                    },
                    "Status": {
                        "type": "boolean",
                        "example": false
                    },
                    "MessageDebug": {
                        "type": "object",
                        "example": {
                            "item_not_found": []
                        }
                    }
                },
                "type": "object"
            },
            "StoreErrorSignature": {
                "description": "401 — the request was refused at the door. **Branch on the `MessageDebug` key**, because the\ncauses need different fixes and the message alone will send you to the wrong one:\n\n| Key | Fix |\n|---|---|\n| `accept_header` | add `Accept: application/json` |\n| `Language not definite` | add `Accept-Language: en` |\n| `Unauthorized` | the bearer token is missing or revoked |\n| `signature_missing` | add `X-Kapitano-Signature` |\n| `signature_malformed` | the header is not `t=…,v1=…` |\n| `signature_mismatch` | wrong secret, or you signed different bytes than you sent |\n| `signature_expired` | your server clock is off — check NTP |\n| `signature_replayed` | re-sign each attempt with a fresh timestamp |",
                "properties": {
                    "Model": {
                        "description": "401 — refused at the door, before the request itself was ever looked at.",
                        "example": null,
                        "nullable": true
                    },
                    "Status": {
                        "type": "boolean",
                        "example": false
                    },
                    "Message": {
                        "type": "string",
                        "example": "The signature is outside the accepted time window. Check the clock on the sending server."
                    },
                    "MessageDebug": {
                        "type": "object",
                        "example": {
                            "signature_expired": []
                        }
                    }
                },
                "type": "object"
            },
            "StoreErrorUnavailable": {
                "description": "503 — temporarily not accepting. Keys: `integration_paused` (intake switched off), `replay_check_unavailable` (we cannot currently prove the request is not a repeat). Both are retryable with the same Idempotency-Key.",
                "properties": {
                    "Model": {
                        "description": "503 — temporarily not accepting. Retryable with the same key.",
                        "example": null,
                        "nullable": true
                    },
                    "Status": {
                        "type": "boolean",
                        "example": false
                    },
                    "MessageDebug": {
                        "type": "object",
                        "example": {
                            "integration_paused": []
                        }
                    }
                },
                "type": "object"
            },
            "StoreErrorValidation": {
                "description": "422 — the payload was refused. Offending fields sit under `MessageDebug.validation`, keyed by the path in your own body. `idempotency_key_required` appears here too, when that header is missing.",
                "properties": {
                    "Model": {
                        "description": "422 — the payload was refused, field by field.",
                        "example": null,
                        "nullable": true
                    },
                    "Status": {
                        "type": "boolean",
                        "example": false
                    },
                    "Message": {
                        "type": "string",
                        "example": "Validation Error"
                    },
                    "MessageDebug": {
                        "type": "object",
                        "example": {
                            "validation": {
                                "pickup.lat": [
                                    "The pickup latitude field is required."
                                ],
                                "payment.status": [
                                    "The payment status field is required."
                                ]
                            }
                        }
                    }
                },
                "type": "object"
            },
            "StoreOrderDetail": {
                "description": "The full state of an order. The same body a status webhook carries, so one parser serves both.",
                "properties": {
                    "uuid": {
                        "description": "The full state of an order — and, deliberately, the same body every status webhook carries,\nso the store writes one parser and a field cannot drift between what they poll and what we\npush.",
                        "type": "string",
                        "format": "uuid"
                    },
                    "external_order_id": {
                        "type": "string",
                        "example": "SO-77120"
                    },
                    "order_number": {
                        "type": "string",
                        "example": "ORD-000482"
                    },
                    "status": {
                        "type": "string",
                        "example": "on_the_way",
                        "enum": [
                            "pending",
                            "assigned",
                            "picked_up",
                            "on_the_way",
                            "delivered",
                            "delivery_failed",
                            "cancelled"
                        ]
                    },
                    "status_label": {
                        "type": "string",
                        "example": "On the way"
                    },
                    "captain": {
                        "description": "Null until a dispatcher assigns one.",
                        "properties": {
                            "name": {
                                "type": "string",
                                "example": "Saeed"
                            },
                            "phone": {
                                "type": "string",
                                "example": "+966500000001"
                            }
                        },
                        "type": "object",
                        "nullable": true
                    },
                    "eta_at": {
                        "description": "Estimated arrival at the customer.",
                        "type": "string",
                        "format": "date-time",
                        "nullable": true
                    },
                    "promised_at": {
                        "description": "The promise you gave us on intake.",
                        "type": "string",
                        "format": "date-time",
                        "nullable": true
                    },
                    "timestamps": {
                        "description": "When each step happened. Null means it has not.",
                        "properties": {
                            "received_at": {
                                "type": "string",
                                "format": "date-time",
                                "nullable": true
                            },
                            "picked_up_at": {
                                "type": "string",
                                "format": "date-time",
                                "nullable": true
                            },
                            "on_the_way_at": {
                                "type": "string",
                                "format": "date-time",
                                "nullable": true
                            },
                            "delivered_at": {
                                "type": "string",
                                "format": "date-time",
                                "nullable": true
                            },
                            "failed_at": {
                                "type": "string",
                                "format": "date-time",
                                "nullable": true
                            },
                            "cancelled_at": {
                                "type": "string",
                                "format": "date-time",
                                "nullable": true
                            }
                        },
                        "type": "object"
                    },
                    "cash": {
                        "properties": {
                            "method": {
                                "type": "string",
                                "enum": [
                                    "cash_on_delivery",
                                    "prepaid"
                                ]
                            },
                            "status": {
                                "type": "string",
                                "nullable": true,
                                "enum": [
                                    "paid",
                                    "unpaid",
                                    "refunded"
                                ]
                            },
                            "amount_to_collect": {
                                "type": "string",
                                "example": "148.00",
                                "nullable": true
                            },
                            "currency": {
                                "type": "string",
                                "example": "SAR"
                            }
                        },
                        "type": "object"
                    },
                    "failure_reason": {
                        "description": "Why the delivery could not be completed.",
                        "type": "string",
                        "nullable": true
                    },
                    "cancel_reason": {
                        "description": "The reason given when the order was called off.",
                        "type": "string",
                        "nullable": true
                    }
                },
                "type": "object"
            },
            "StoreOrderSummary": {
                "description": "What `POST /orders` answers with — enough to file the order against yours.",
                "properties": {
                    "uuid": {
                        "description": "Our identifier. **Store this**: every later call and every webhook uses it.",
                        "type": "string",
                        "format": "uuid",
                        "example": "9c4f2e10-7b3a-4d61-9f28-0a1b2c3d4e5f"
                    },
                    "order_number": {
                        "description": "The human-readable number our operations team and the captain see.",
                        "type": "string",
                        "example": "ORD-000482"
                    },
                    "external_order_id": {
                        "description": "Your own reference, echoed back.",
                        "type": "string",
                        "example": "SO-77120"
                    },
                    "status": {
                        "type": "string",
                        "example": "pending",
                        "enum": [
                            "pending",
                            "assigned",
                            "picked_up",
                            "on_the_way",
                            "delivered",
                            "delivery_failed",
                            "cancelled"
                        ]
                    },
                    "status_label": {
                        "description": "The status translated into the request's Accept-Language.",
                        "type": "string",
                        "example": "Pending"
                    },
                    "created_at": {
                        "type": "string",
                        "format": "date-time",
                        "example": "2026-09-18T11:04:22+03:00"
                    }
                },
                "type": "object"
            },
            "StoreWebhookPayload": {
                "description": "The body we `POST` to your webhook URL. There is no endpoint to call here; this documents\nwhat arrives at yours.\n\n**`sequence` is the field that matters.** It only ever increases per order, so keeping the\nhighest you have processed and discarding anything not greater than it is the whole answer\nto out-of-order retries. `event_id` is unique per event and is how you drop duplicates.\n\nVerify `X-Kapitano-Signature` with your **webhook** secret and the same algorithm you sign\nwith — see the API description.",
                "properties": {
                    "event": {
                        "description": "The webhook body. Documented as a schema because there is no endpoint here to hang it on —\nthis is what we send *them*.",
                        "type": "string",
                        "example": "order.on_the_way",
                        "enum": [
                            "order.received",
                            "order.assigned",
                            "order.picked_up",
                            "order.on_the_way",
                            "order.delivered",
                            "order.delivery_failed",
                            "order.cancelled",
                            "order.updated",
                            "order.address_details"
                        ]
                    },
                    "event_id": {
                        "description": "Unique per event. Your dedupe key.",
                        "type": "string",
                        "format": "uuid"
                    },
                    "occurred_at": {
                        "description": "Advisory only — order by `sequence`, not by this.",
                        "type": "string",
                        "format": "date-time"
                    },
                    "sequence": {
                        "description": "Monotonic per order. Discard any event whose sequence is not greater than the last you processed.",
                        "type": "integer",
                        "example": 1487,
                        "nullable": true
                    },
                    "order": {
                        "$ref": "#/components/schemas/StoreOrderDetail"
                    }
                },
                "type": "object"
            }
        },
        "securitySchemes": {
            "storeAuth": {
                "type": "http",
                "description": "The bearer token issued to your integration. Enter in format (Bearer <token>). It identifies you; the X-Kapitano-Signature header proves the request itself.",
                "bearerFormat": "Sanctum",
                "scheme": "bearer"
            }
        }
    },
    "tags": [
        {
            "name": "Store — Connectivity",
            "description": "Check the credentials, the signature and the clock before sending anything real."
        },
        {
            "name": "Store — Orders",
            "description": "Hand us an order, read it back, cancel it, and correct its payment."
        }
    ]
}