{
    "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 SYP when omitted.",
                                        "type": "string",
                                        "example": "SYP",
                                        "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": {
                                                    "description": "Your product code. It has its own column and is returned as you sent it.",
                                                    "type": "string",
                                                    "nullable": true,
                                                    "maxLength": 255
                                                },
                                                "note": {
                                                    "type": "string",
                                                    "nullable": true,
                                                    "maxLength": 255
                                                },
                                                "image_url": {
                                                    "description": "An https link to your own picture of this line. We store the link and never fetch it, so it must stay reachable from a phone; if the path rotates, the image simply stops loading.",
                                                    "type": "string",
                                                    "format": "uri",
                                                    "example": "https://cdn.example.sy/shirt-red.jpg",
                                                    "nullable": true,
                                                    "maxLength": 2048
                                                },
                                                "variant": {
                                                    "description": "What distinguishes this line from another with the same name - colour, size, flavour, model. Free-form, because a shop selling shoes and a shop selling cake do not agree on what an attribute is. At most 10 keys, each value at most 120 characters. Shown to the captain at the counter and to the back office; never filtered or totalled by us.",
                                                    "type": "object",
                                                    "example": {
                                                        "color": "red",
                                                        "size": "L"
                                                    },
                                                    "nullable": true,
                                                    "additionalProperties": {
                                                        "type": "string"
                                                    }
                                                }
                                            },
                                            "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": "SYP",
                                "delivery_fee": 15,
                                "promised_at": "2026-09-18T12:15:00+03:00",
                                "items": [
                                    {
                                        "name": "برجر لحم",
                                        "quantity": 2,
                                        "unit_price": 45,
                                        "sku": "BRG-01",
                                        "image_url": "https://cdn.example.sy/burger.jpg",
                                        "variant": {
                                            "size": "كبير",
                                            "doneness": "وسط"
                                        }
                                    },
                                    {
                                        "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
                                                },
                                                "image_url": {
                                                    "type": "string",
                                                    "format": "uri",
                                                    "nullable": true
                                                },
                                                "variant": {
                                                    "type": "object",
                                                    "nullable": true,
                                                    "additionalProperties": {
                                                        "type": "string"
                                                    }
                                                }
                                            },
                                            "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": "SYP"
                            }
                        },
                        "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."
        }
    ]
}