{
    "openapi": "3.1.0",
    "info": {
        "title": "PalomaPOS Platform API",
        "version": "1.0.0-draft",
        "description": "Public REST API for third-party apps acting on behalf of a PalomaPOS (USA) or Paloma365 (CIS) business with the owner's consent. One contract for both markets; each market has its own host and its own app registry, so an app is registered per market (separate `client_id`/`client_secret`).\n\n**Quickstart**\n\n1. Register your app yourself in the dashboard of the market host — Settings → Developers (sandbox: register a free test business at https://sandbox.paloma365.com/register): name, logo, privacy and terms URLs, exact `https://` redirect URIs, the scopes you need. You receive `client_id` (`ppc_…`) and `client_secret` (`ppcs_…`, shown once) at once, with no review.\n2. Send the business owner to `GET /platform/oauth/authorize` with `response_type=code`, your `client_id`, `redirect_uri`, `scope`, `state` and a PKCE `code_challenge` (`S256`). Only the account owner can approve.\n3. Exchange the returned `code` at `POST /platform/oauth/token` (`grant_type=authorization_code`, `redirect_uri`, `code_verifier`; client authentication `client_secret_basic` or `client_secret_post`). Access tokens (`ppat_…`) live 1 hour; with `offline_access` you also get a rotating refresh token (`pprt_…`).\n4. Call the API with `Authorization: Bearer ppat_…` — start with `GET /me`, then page through lists with `limit`/`cursor` and keep them current with `since=<sync_token>`.\n5. Create orders with `POST /orders` and an `Idempotency-Key`; the server prices every order, and a cart it cannot price is refused with `422 quote_unsupported`. Track status by polling `GET /orders?since=…` (no webhooks in v1).\n\n**Documentation:** the integration guide [guide.md](guide.md) (OAuth details, conventions, sync, idempotency, rate limits, orders, errors, and a checklist for AI coding agents) and [llms.txt](../llms.txt) for AI tools. Both are served on every API host next to this file.\n\n**Conventions:** ids are strings; money is a decimal string with exactly two decimals plus the account `currency`, never a float; times are ISO 8601 with an offset; every error uses the envelope `{\"error\":{\"code\",\"message\",\"retryable\",\"request_id\",\"details\"}}` (codes on the `Error` schema); every response carries `X-Request-Id` (quote it to support) and `PalomaPOS-Api-Version: 1`; within v1 fields, values and codes are only ever added. Rate limits per app and account: 600 reads and 60 writes per minute (`429` + `Retry-After`).\n\n`x-palomapos-phase` marks the rollout phase of each operation: 1a connect, profile, catalog; 1b order history, customers, staff, reports; 2 orders (always priced by the server) and cancel, statuses via the `since` cursor; 3 quote, `expected_total`, payments; `payments` payment providers for online orders (`payments:process`, behind its own switch); `later` webhooks. An operation is live only after its phase ships on the market.",
        "contact": {
            "name": "Paloma365 Platform API",
            "email": "info@paloma365.com"
        }
    },
    "servers": [
        {
            "url": "https://sandbox-api.paloma365.com/platform/v1",
            "description": "Paloma365 — CIS (test host)"
        }
    ],
    "tags": [
        {
            "name": "Account",
            "description": "Connection check and business profile (phase 1a)"
        },
        {
            "name": "Catalog",
            "description": "Categories, items, modifiers, menus, stop list (phase 1a)"
        },
        {
            "name": "Orders",
            "description": "Read (1b), create unpaid and cancel (2), quote and payments for prepaid orders (3)"
        },
        {
            "name": "History",
            "description": "Customers, staff, shifts, reports (phase 1b)"
        },
        {
            "name": "Payments",
            "description": "Payment providers: take payments for online orders (QR menu) — see the Payment providers section of guide.md (phase payments)"
        }
    ],
    "paths": {
        "/me": {
            "get": {
                "summary": "Who am I: app, account, granted scopes",
                "tags": [
                    "Account"
                ],
                "security": [
                    {
                        "oauth2": []
                    },
                    {
                        "personalKey": []
                    }
                ],
                "x-palomapos-phase": "1a",
                "responses": {
                    "200": {
                        "description": "OK",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Me"
                                },
                                "example": {
                                    "app": {
                                        "client_id": "ppc_0123456789abcdef0123456789abcdef",
                                        "name": "Example Orders App",
                                        "kind": "app"
                                    },
                                    "account_id": "5120",
                                    "scopes": [
                                        "account:read",
                                        "catalog:read",
                                        "orders:read",
                                        "orders:write",
                                        "offline_access"
                                    ],
                                    "token_expires_at": "2026-09-29T18:52:10-04:00"
                                }
                            }
                        },
                        "headers": {
                            "X-Request-Id": {
                                "$ref": "#/components/headers/X-Request-Id"
                            },
                            "PalomaPOS-Api-Version": {
                                "$ref": "#/components/headers/PalomaPOS-Api-Version"
                            }
                        }
                    },
                    "401": {
                        "description": "invalid_token",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                },
                                "example": {
                                    "error": {
                                        "code": "invalid_token",
                                        "message": "The access token is missing, expired or revoked.",
                                        "retryable": false,
                                        "request_id": "req_4f1c2a9be07d5e8a1b3c6d20",
                                        "details": {}
                                    }
                                }
                            }
                        },
                        "headers": {
                            "X-Request-Id": {
                                "$ref": "#/components/headers/X-Request-Id"
                            },
                            "PalomaPOS-Api-Version": {
                                "$ref": "#/components/headers/PalomaPOS-Api-Version"
                            }
                        }
                    },
                    "403": {
                        "description": "insufficient_scope / not_owner",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                },
                                "example": {
                                    "error": {
                                        "code": "insufficient_scope",
                                        "message": "The access token does not grant the scope required by this operation.",
                                        "retryable": false,
                                        "request_id": "req_4f1c2a9be07d5e8a1b3c6d20",
                                        "details": {
                                            "required_scope": "account:read"
                                        }
                                    }
                                }
                            }
                        },
                        "headers": {
                            "X-Request-Id": {
                                "$ref": "#/components/headers/X-Request-Id"
                            },
                            "PalomaPOS-Api-Version": {
                                "$ref": "#/components/headers/PalomaPOS-Api-Version"
                            }
                        }
                    },
                    "429": {
                        "description": "rate_limited",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                },
                                "example": {
                                    "error": {
                                        "code": "rate_limited",
                                        "message": "Rate limit exceeded: 600 read requests per minute for this app and account.",
                                        "retryable": true,
                                        "request_id": "req_4f1c2a9be07d5e8a1b3c6d20",
                                        "details": {
                                            "limit": 600,
                                            "kind": "read",
                                            "retry_after": 17
                                        }
                                    }
                                }
                            }
                        },
                        "headers": {
                            "Retry-After": {
                                "$ref": "#/components/headers/Retry-After"
                            },
                            "X-Request-Id": {
                                "$ref": "#/components/headers/X-Request-Id"
                            },
                            "PalomaPOS-Api-Version": {
                                "$ref": "#/components/headers/PalomaPOS-Api-Version"
                            }
                        }
                    },
                    "500": {
                        "$ref": "#/components/responses/InternalError"
                    },
                    "503": {
                        "$ref": "#/components/responses/Unavailable"
                    }
                },
                "operationId": "getMe"
            }
        },
        "/account": {
            "get": {
                "summary": "Business profile",
                "tags": [
                    "Account"
                ],
                "security": [
                    {
                        "oauth2": [
                            "account:read"
                        ]
                    },
                    {
                        "personalKey": []
                    }
                ],
                "x-palomapos-phase": "1a",
                "responses": {
                    "200": {
                        "description": "OK",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Account"
                                },
                                "example": {
                                    "id": "5120",
                                    "name": "Harbor Street Cafe",
                                    "currency": "USD",
                                    "timezone": "America/New_York",
                                    "country": "US",
                                    "capabilities": {
                                        "order_writes": {
                                            "available": true,
                                            "reason": null
                                        }
                                    }
                                }
                            }
                        },
                        "headers": {
                            "X-Request-Id": {
                                "$ref": "#/components/headers/X-Request-Id"
                            },
                            "PalomaPOS-Api-Version": {
                                "$ref": "#/components/headers/PalomaPOS-Api-Version"
                            }
                        }
                    },
                    "401": {
                        "description": "invalid_token",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                },
                                "example": {
                                    "error": {
                                        "code": "invalid_token",
                                        "message": "The access token is missing, expired or revoked.",
                                        "retryable": false,
                                        "request_id": "req_4f1c2a9be07d5e8a1b3c6d20",
                                        "details": {}
                                    }
                                }
                            }
                        },
                        "headers": {
                            "X-Request-Id": {
                                "$ref": "#/components/headers/X-Request-Id"
                            },
                            "PalomaPOS-Api-Version": {
                                "$ref": "#/components/headers/PalomaPOS-Api-Version"
                            }
                        }
                    },
                    "403": {
                        "description": "insufficient_scope / not_owner",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                },
                                "example": {
                                    "error": {
                                        "code": "insufficient_scope",
                                        "message": "The access token does not grant the scope required by this operation.",
                                        "retryable": false,
                                        "request_id": "req_4f1c2a9be07d5e8a1b3c6d20",
                                        "details": {
                                            "required_scope": "account:read"
                                        }
                                    }
                                }
                            }
                        },
                        "headers": {
                            "X-Request-Id": {
                                "$ref": "#/components/headers/X-Request-Id"
                            },
                            "PalomaPOS-Api-Version": {
                                "$ref": "#/components/headers/PalomaPOS-Api-Version"
                            }
                        }
                    },
                    "429": {
                        "description": "rate_limited",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                },
                                "example": {
                                    "error": {
                                        "code": "rate_limited",
                                        "message": "Rate limit exceeded: 600 read requests per minute for this app and account.",
                                        "retryable": true,
                                        "request_id": "req_4f1c2a9be07d5e8a1b3c6d20",
                                        "details": {
                                            "limit": 600,
                                            "kind": "read",
                                            "retry_after": 17
                                        }
                                    }
                                }
                            }
                        },
                        "headers": {
                            "Retry-After": {
                                "$ref": "#/components/headers/Retry-After"
                            },
                            "X-Request-Id": {
                                "$ref": "#/components/headers/X-Request-Id"
                            },
                            "PalomaPOS-Api-Version": {
                                "$ref": "#/components/headers/PalomaPOS-Api-Version"
                            }
                        }
                    },
                    "500": {
                        "$ref": "#/components/responses/InternalError"
                    },
                    "503": {
                        "$ref": "#/components/responses/Unavailable"
                    }
                },
                "operationId": "getAccount",
                "description": "Business profile: display name, currency, time zone, country."
            }
        },
        "/locations": {
            "get": {
                "summary": "Locations with hours and fulfillment modes",
                "tags": [
                    "Account"
                ],
                "security": [
                    {
                        "oauth2": [
                            "account:read"
                        ]
                    },
                    {
                        "personalKey": []
                    }
                ],
                "x-palomapos-phase": "1a",
                "responses": {
                    "200": {
                        "description": "OK",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "type": "array",
                                            "items": {
                                                "$ref": "#/components/schemas/Location"
                                            }
                                        },
                                        "next_cursor": {
                                            "type": [
                                                "string",
                                                "null"
                                            ]
                                        }
                                    },
                                    "required": [
                                        "data",
                                        "next_cursor"
                                    ]
                                },
                                "example": {
                                    "data": [
                                        {
                                            "id": "3",
                                            "name": "Harbor Street Cafe — Downtown",
                                            "phone": "+13055550199",
                                            "address": {
                                                "line1": "100 Example Ave",
                                                "city": "Miami",
                                                "region": "FL",
                                                "postal_code": "33101",
                                                "country": "US",
                                                "formatted": "100 Example Ave, Miami, FL 33101"
                                            },
                                            "timezone": "America/New_York",
                                            "weekly_hours": {
                                                "mon": [
                                                    {
                                                        "opens": "09:00",
                                                        "closes": "22:00"
                                                    }
                                                ],
                                                "tue": [
                                                    {
                                                        "opens": "09:00",
                                                        "closes": "22:00"
                                                    }
                                                ],
                                                "wed": [
                                                    {
                                                        "opens": "09:00",
                                                        "closes": "22:00"
                                                    }
                                                ],
                                                "thu": [
                                                    {
                                                        "opens": "09:00",
                                                        "closes": "22:00"
                                                    }
                                                ],
                                                "fri": [
                                                    {
                                                        "opens": "09:00",
                                                        "closes": "22:00"
                                                    }
                                                ],
                                                "sat": [
                                                    {
                                                        "opens": "09:00",
                                                        "closes": "22:00"
                                                    }
                                                ],
                                                "sun": [
                                                    {
                                                        "opens": "09:00",
                                                        "closes": "22:00"
                                                    }
                                                ]
                                            },
                                            "fulfillment": {
                                                "pickup": {
                                                    "enabled": true,
                                                    "min_order_amount": null,
                                                    "fee": null
                                                },
                                                "delivery": {
                                                    "enabled": true,
                                                    "min_order_amount": "15.00",
                                                    "fee": "5.00"
                                                },
                                                "dine_in": {
                                                    "enabled": true,
                                                    "min_order_amount": null,
                                                    "fee": null
                                                }
                                            },
                                            "currency": "USD",
                                            "money_step": "0.01",
                                            "default_menu_id": "7",
                                            "updated_at": "2026-09-29T08:15:00-04:00"
                                        }
                                    ],
                                    "next_cursor": null
                                }
                            }
                        },
                        "headers": {
                            "X-Request-Id": {
                                "$ref": "#/components/headers/X-Request-Id"
                            },
                            "PalomaPOS-Api-Version": {
                                "$ref": "#/components/headers/PalomaPOS-Api-Version"
                            }
                        }
                    },
                    "400": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                },
                                "example": {
                                    "error": {
                                        "code": "invalid_request",
                                        "message": "limit must be an integer between 1 and 200.",
                                        "retryable": false,
                                        "request_id": "req_4f1c2a9be07d5e8a1b3c6d20",
                                        "details": {
                                            "fields": {
                                                "limit": "out_of_range"
                                            }
                                        }
                                    }
                                }
                            }
                        },
                        "description": "invalid_request — limit, cursor or since is malformed, or was issued for another list",
                        "headers": {
                            "X-Request-Id": {
                                "$ref": "#/components/headers/X-Request-Id"
                            },
                            "PalomaPOS-Api-Version": {
                                "$ref": "#/components/headers/PalomaPOS-Api-Version"
                            }
                        }
                    },
                    "401": {
                        "description": "invalid_token",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                },
                                "example": {
                                    "error": {
                                        "code": "invalid_token",
                                        "message": "The access token is missing, expired or revoked.",
                                        "retryable": false,
                                        "request_id": "req_4f1c2a9be07d5e8a1b3c6d20",
                                        "details": {}
                                    }
                                }
                            }
                        },
                        "headers": {
                            "X-Request-Id": {
                                "$ref": "#/components/headers/X-Request-Id"
                            },
                            "PalomaPOS-Api-Version": {
                                "$ref": "#/components/headers/PalomaPOS-Api-Version"
                            }
                        }
                    },
                    "403": {
                        "description": "insufficient_scope / not_owner",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                },
                                "example": {
                                    "error": {
                                        "code": "insufficient_scope",
                                        "message": "The access token does not grant the scope required by this operation.",
                                        "retryable": false,
                                        "request_id": "req_4f1c2a9be07d5e8a1b3c6d20",
                                        "details": {
                                            "required_scope": "account:read"
                                        }
                                    }
                                }
                            }
                        },
                        "headers": {
                            "X-Request-Id": {
                                "$ref": "#/components/headers/X-Request-Id"
                            },
                            "PalomaPOS-Api-Version": {
                                "$ref": "#/components/headers/PalomaPOS-Api-Version"
                            }
                        }
                    },
                    "429": {
                        "description": "rate_limited",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                },
                                "example": {
                                    "error": {
                                        "code": "rate_limited",
                                        "message": "Rate limit exceeded: 600 read requests per minute for this app and account.",
                                        "retryable": true,
                                        "request_id": "req_4f1c2a9be07d5e8a1b3c6d20",
                                        "details": {
                                            "limit": 600,
                                            "kind": "read",
                                            "retry_after": 17
                                        }
                                    }
                                }
                            }
                        },
                        "headers": {
                            "Retry-After": {
                                "$ref": "#/components/headers/Retry-After"
                            },
                            "X-Request-Id": {
                                "$ref": "#/components/headers/X-Request-Id"
                            },
                            "PalomaPOS-Api-Version": {
                                "$ref": "#/components/headers/PalomaPOS-Api-Version"
                            }
                        }
                    },
                    "500": {
                        "$ref": "#/components/responses/InternalError"
                    },
                    "503": {
                        "$ref": "#/components/responses/Unavailable"
                    }
                },
                "parameters": [
                    {
                        "name": "limit",
                        "in": "query",
                        "schema": {
                            "type": "integer",
                            "minimum": 1,
                            "maximum": 200,
                            "default": 100
                        }
                    },
                    {
                        "name": "cursor",
                        "in": "query",
                        "schema": {
                            "type": "string"
                        }
                    }
                ],
                "operationId": "getLocations",
                "description": "Active locations with address, phone, time zone, working hours, online-ordering modes (minimum order, delivery fee), money step and the pinned menu. Pages by id; no `since` (the list is short — re-read it). Location passwords and logins are never exposed."
            }
        },
        "/taxes": {
            "get": {
                "summary": "Taxes and fees as the POS applies them",
                "tags": [
                    "Account"
                ],
                "security": [
                    {
                        "oauth2": [
                            "account:read"
                        ]
                    },
                    {
                        "personalKey": []
                    }
                ],
                "x-palomapos-phase": "1a",
                "responses": {
                    "200": {
                        "description": "OK",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Taxes"
                                },
                                "example": {
                                    "rounding": "half_away_from_zero",
                                    "money_step": "0.01",
                                    "default_tax": {
                                        "id": "1",
                                        "name": "Sales Tax",
                                        "rate": "8.875",
                                        "included": false,
                                        "kind": "tax"
                                    },
                                    "default_tax_ambiguous": false,
                                    "taxes": [
                                        {
                                            "id": "1",
                                            "name": "Sales Tax",
                                            "rate": "8.875",
                                            "included": false,
                                            "kind": "tax",
                                            "is_default": true,
                                            "deleted": false
                                        },
                                        {
                                            "id": "4",
                                            "name": "Delivery service fee",
                                            "rate": "3",
                                            "included": false,
                                            "kind": "fee",
                                            "is_default": false,
                                            "deleted": false
                                        }
                                    ],
                                    "rules": "Each order line carries at most one tax. If default_tax is added on top (included = false) with a positive rate, it applies to every item. Otherwise the item's own tax (Item.tax_id) applies and is always included in the price, unless its rate is negative (no tax). Otherwise an included default_tax applies; otherwise the line is untaxed. Item.effective_tax is this rule already applied. Tax is computed per line on the line total (unit price plus modifiers, times quantity, snapped to money_step) and rounded half away from zero: added tax = total x rate; included tax = total x rate / (1 + rate). Delivery fees and tips are not taxed. Automatic POS charges (order-type fees, service charge, surcharge or cash-discount programs) are not part of this estimate. When default_tax_ambiguous is true the POS choice of default tax cannot be predicted and effective_tax is null for every item."
                                }
                            }
                        },
                        "headers": {
                            "X-Request-Id": {
                                "$ref": "#/components/headers/X-Request-Id"
                            },
                            "PalomaPOS-Api-Version": {
                                "$ref": "#/components/headers/PalomaPOS-Api-Version"
                            }
                        }
                    },
                    "401": {
                        "description": "invalid_token",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                },
                                "example": {
                                    "error": {
                                        "code": "invalid_token",
                                        "message": "The access token is missing, expired or revoked.",
                                        "retryable": false,
                                        "request_id": "req_4f1c2a9be07d5e8a1b3c6d20",
                                        "details": {}
                                    }
                                }
                            }
                        },
                        "headers": {
                            "X-Request-Id": {
                                "$ref": "#/components/headers/X-Request-Id"
                            },
                            "PalomaPOS-Api-Version": {
                                "$ref": "#/components/headers/PalomaPOS-Api-Version"
                            }
                        }
                    },
                    "403": {
                        "description": "insufficient_scope / not_owner",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                },
                                "example": {
                                    "error": {
                                        "code": "insufficient_scope",
                                        "message": "The access token does not grant the scope required by this operation.",
                                        "retryable": false,
                                        "request_id": "req_4f1c2a9be07d5e8a1b3c6d20",
                                        "details": {
                                            "required_scope": "account:read"
                                        }
                                    }
                                }
                            }
                        },
                        "headers": {
                            "X-Request-Id": {
                                "$ref": "#/components/headers/X-Request-Id"
                            },
                            "PalomaPOS-Api-Version": {
                                "$ref": "#/components/headers/PalomaPOS-Api-Version"
                            }
                        }
                    },
                    "429": {
                        "description": "rate_limited",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                },
                                "example": {
                                    "error": {
                                        "code": "rate_limited",
                                        "message": "Rate limit exceeded: 600 read requests per minute for this app and account.",
                                        "retryable": true,
                                        "request_id": "req_4f1c2a9be07d5e8a1b3c6d20",
                                        "details": {
                                            "limit": 600,
                                            "kind": "read",
                                            "retry_after": 17
                                        }
                                    }
                                }
                            }
                        },
                        "headers": {
                            "Retry-After": {
                                "$ref": "#/components/headers/Retry-After"
                            },
                            "X-Request-Id": {
                                "$ref": "#/components/headers/X-Request-Id"
                            },
                            "PalomaPOS-Api-Version": {
                                "$ref": "#/components/headers/PalomaPOS-Api-Version"
                            }
                        }
                    },
                    "500": {
                        "$ref": "#/components/responses/InternalError"
                    },
                    "503": {
                        "$ref": "#/components/responses/Unavailable"
                    }
                },
                "operationId": "getTaxes",
                "description": "Taxes and fees as the POS applies them, with the rule that decides the single tax of a line. Item.effective_tax already applies it per item."
            }
        },
        "/payment-types": {
            "get": {
                "summary": "Payment types of the account",
                "tags": [
                    "Account"
                ],
                "security": [
                    {
                        "oauth2": [
                            "account:read"
                        ]
                    },
                    {
                        "personalKey": []
                    }
                ],
                "x-palomapos-phase": "1a",
                "responses": {
                    "200": {
                        "description": "OK",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "type": "array",
                                            "items": {
                                                "$ref": "#/components/schemas/PaymentType"
                                            }
                                        },
                                        "next_cursor": {
                                            "type": [
                                                "string",
                                                "null"
                                            ]
                                        }
                                    },
                                    "required": [
                                        "data",
                                        "next_cursor"
                                    ]
                                },
                                "example": {
                                    "data": [
                                        {
                                            "id": "1",
                                            "name": "Cash",
                                            "kind": "cash",
                                            "deleted": false,
                                            "updated_at": "2026-09-29T08:00:00-04:00"
                                        },
                                        {
                                            "id": "2",
                                            "name": "Card",
                                            "kind": "card",
                                            "deleted": false,
                                            "updated_at": "2026-09-29T08:00:00-04:00"
                                        },
                                        {
                                            "id": "31",
                                            "name": "Example Orders App",
                                            "kind": "other",
                                            "deleted": false,
                                            "updated_at": "2026-09-29T17:53:02-04:00"
                                        }
                                    ],
                                    "next_cursor": null
                                }
                            }
                        },
                        "headers": {
                            "X-Request-Id": {
                                "$ref": "#/components/headers/X-Request-Id"
                            },
                            "PalomaPOS-Api-Version": {
                                "$ref": "#/components/headers/PalomaPOS-Api-Version"
                            }
                        }
                    },
                    "400": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                },
                                "example": {
                                    "error": {
                                        "code": "invalid_request",
                                        "message": "limit must be an integer between 1 and 200.",
                                        "retryable": false,
                                        "request_id": "req_4f1c2a9be07d5e8a1b3c6d20",
                                        "details": {
                                            "fields": {
                                                "limit": "out_of_range"
                                            }
                                        }
                                    }
                                }
                            }
                        },
                        "description": "invalid_request — limit, cursor or since is malformed, or was issued for another list",
                        "headers": {
                            "X-Request-Id": {
                                "$ref": "#/components/headers/X-Request-Id"
                            },
                            "PalomaPOS-Api-Version": {
                                "$ref": "#/components/headers/PalomaPOS-Api-Version"
                            }
                        }
                    },
                    "401": {
                        "description": "invalid_token",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                },
                                "example": {
                                    "error": {
                                        "code": "invalid_token",
                                        "message": "The access token is missing, expired or revoked.",
                                        "retryable": false,
                                        "request_id": "req_4f1c2a9be07d5e8a1b3c6d20",
                                        "details": {}
                                    }
                                }
                            }
                        },
                        "headers": {
                            "X-Request-Id": {
                                "$ref": "#/components/headers/X-Request-Id"
                            },
                            "PalomaPOS-Api-Version": {
                                "$ref": "#/components/headers/PalomaPOS-Api-Version"
                            }
                        }
                    },
                    "403": {
                        "description": "insufficient_scope / not_owner",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                },
                                "example": {
                                    "error": {
                                        "code": "insufficient_scope",
                                        "message": "The access token does not grant the scope required by this operation.",
                                        "retryable": false,
                                        "request_id": "req_4f1c2a9be07d5e8a1b3c6d20",
                                        "details": {
                                            "required_scope": "account:read"
                                        }
                                    }
                                }
                            }
                        },
                        "headers": {
                            "X-Request-Id": {
                                "$ref": "#/components/headers/X-Request-Id"
                            },
                            "PalomaPOS-Api-Version": {
                                "$ref": "#/components/headers/PalomaPOS-Api-Version"
                            }
                        }
                    },
                    "429": {
                        "description": "rate_limited",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                },
                                "example": {
                                    "error": {
                                        "code": "rate_limited",
                                        "message": "Rate limit exceeded: 600 read requests per minute for this app and account.",
                                        "retryable": true,
                                        "request_id": "req_4f1c2a9be07d5e8a1b3c6d20",
                                        "details": {
                                            "limit": 600,
                                            "kind": "read",
                                            "retry_after": 17
                                        }
                                    }
                                }
                            }
                        },
                        "headers": {
                            "Retry-After": {
                                "$ref": "#/components/headers/Retry-After"
                            },
                            "X-Request-Id": {
                                "$ref": "#/components/headers/X-Request-Id"
                            },
                            "PalomaPOS-Api-Version": {
                                "$ref": "#/components/headers/PalomaPOS-Api-Version"
                            }
                        }
                    },
                    "500": {
                        "$ref": "#/components/responses/InternalError"
                    },
                    "503": {
                        "$ref": "#/components/responses/Unavailable"
                    }
                },
                "operationId": "getPaymentTypes",
                "description": "Payment types with their kind (cash / card / other), deleted ones included. Pages by id."
            }
        },
        "/categories": {
            "get": {
                "summary": "Category tree",
                "tags": [
                    "Catalog"
                ],
                "security": [
                    {
                        "oauth2": [
                            "catalog:read"
                        ]
                    },
                    {
                        "personalKey": []
                    }
                ],
                "x-palomapos-phase": "1a",
                "responses": {
                    "200": {
                        "description": "OK",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "type": "array",
                                            "items": {
                                                "oneOf": [
                                                    {
                                                        "$ref": "#/components/schemas/Category"
                                                    },
                                                    {
                                                        "$ref": "#/components/schemas/Deleted"
                                                    }
                                                ]
                                            }
                                        },
                                        "next_cursor": {
                                            "type": [
                                                "string",
                                                "null"
                                            ]
                                        },
                                        "sync_token": {
                                            "type": [
                                                "string",
                                                "null"
                                            ],
                                            "description": "null on every page but the last; on the last page pass it as `since` to receive only what changed afterwards (deletions included)."
                                        }
                                    },
                                    "required": [
                                        "data",
                                        "next_cursor",
                                        "sync_token"
                                    ]
                                },
                                "example": {
                                    "data": [
                                        {
                                            "id": "20",
                                            "name": "Burgers",
                                            "parent_id": null,
                                            "sort_index": 1,
                                            "deleted": false,
                                            "updated_at": "2026-09-29T08:10:00-04:00"
                                        },
                                        {
                                            "id": "21",
                                            "name": "Sides",
                                            "parent_id": null,
                                            "sort_index": 2,
                                            "deleted": false,
                                            "updated_at": "2026-09-29T08:10:05-04:00"
                                        },
                                        {
                                            "id": "25",
                                            "deleted": true,
                                            "updated_at": "2026-09-29T08:12:40-04:00"
                                        }
                                    ],
                                    "next_cursor": null,
                                    "sync_token": "eyJ2IjoxLCJ0IjoicyIsInIiOiJpdGVtcyIsInciOjE3OTAwMDAwMDB9.Qm9ndXNTaWduYXR1cmU"
                                }
                            }
                        },
                        "headers": {
                            "X-Request-Id": {
                                "$ref": "#/components/headers/X-Request-Id"
                            },
                            "PalomaPOS-Api-Version": {
                                "$ref": "#/components/headers/PalomaPOS-Api-Version"
                            }
                        }
                    },
                    "400": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                },
                                "example": {
                                    "error": {
                                        "code": "invalid_request",
                                        "message": "limit must be an integer between 1 and 200.",
                                        "retryable": false,
                                        "request_id": "req_4f1c2a9be07d5e8a1b3c6d20",
                                        "details": {
                                            "fields": {
                                                "limit": "out_of_range"
                                            }
                                        }
                                    }
                                }
                            }
                        },
                        "description": "invalid_request — limit, cursor or since is malformed, or was issued for another list",
                        "headers": {
                            "X-Request-Id": {
                                "$ref": "#/components/headers/X-Request-Id"
                            },
                            "PalomaPOS-Api-Version": {
                                "$ref": "#/components/headers/PalomaPOS-Api-Version"
                            }
                        }
                    },
                    "401": {
                        "description": "invalid_token",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                },
                                "example": {
                                    "error": {
                                        "code": "invalid_token",
                                        "message": "The access token is missing, expired or revoked.",
                                        "retryable": false,
                                        "request_id": "req_4f1c2a9be07d5e8a1b3c6d20",
                                        "details": {}
                                    }
                                }
                            }
                        },
                        "headers": {
                            "X-Request-Id": {
                                "$ref": "#/components/headers/X-Request-Id"
                            },
                            "PalomaPOS-Api-Version": {
                                "$ref": "#/components/headers/PalomaPOS-Api-Version"
                            }
                        }
                    },
                    "403": {
                        "description": "insufficient_scope / not_owner",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                },
                                "example": {
                                    "error": {
                                        "code": "insufficient_scope",
                                        "message": "The access token does not grant the scope required by this operation.",
                                        "retryable": false,
                                        "request_id": "req_4f1c2a9be07d5e8a1b3c6d20",
                                        "details": {
                                            "required_scope": "catalog:read"
                                        }
                                    }
                                }
                            }
                        },
                        "headers": {
                            "X-Request-Id": {
                                "$ref": "#/components/headers/X-Request-Id"
                            },
                            "PalomaPOS-Api-Version": {
                                "$ref": "#/components/headers/PalomaPOS-Api-Version"
                            }
                        }
                    },
                    "410": {
                        "description": "sync_token_expired — do a full pass",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                },
                                "example": {
                                    "error": {
                                        "code": "sync_token_expired",
                                        "message": "The sync_token is older than 20 days; deletions since then are no longer known. Do a full pass without since.",
                                        "retryable": false,
                                        "request_id": "req_4f1c2a9be07d5e8a1b3c6d20",
                                        "details": {
                                            "max_age_days": 20
                                        }
                                    }
                                }
                            }
                        },
                        "headers": {
                            "X-Request-Id": {
                                "$ref": "#/components/headers/X-Request-Id"
                            },
                            "PalomaPOS-Api-Version": {
                                "$ref": "#/components/headers/PalomaPOS-Api-Version"
                            }
                        }
                    },
                    "429": {
                        "description": "rate_limited",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                },
                                "example": {
                                    "error": {
                                        "code": "rate_limited",
                                        "message": "Rate limit exceeded: 600 read requests per minute for this app and account.",
                                        "retryable": true,
                                        "request_id": "req_4f1c2a9be07d5e8a1b3c6d20",
                                        "details": {
                                            "limit": 600,
                                            "kind": "read",
                                            "retry_after": 17
                                        }
                                    }
                                }
                            }
                        },
                        "headers": {
                            "Retry-After": {
                                "$ref": "#/components/headers/Retry-After"
                            },
                            "X-Request-Id": {
                                "$ref": "#/components/headers/X-Request-Id"
                            },
                            "PalomaPOS-Api-Version": {
                                "$ref": "#/components/headers/PalomaPOS-Api-Version"
                            }
                        }
                    },
                    "500": {
                        "$ref": "#/components/responses/InternalError"
                    },
                    "503": {
                        "$ref": "#/components/responses/Unavailable"
                    }
                },
                "parameters": [
                    {
                        "name": "limit",
                        "in": "query",
                        "schema": {
                            "type": "integer",
                            "minimum": 1,
                            "maximum": 200,
                            "default": 100
                        }
                    },
                    {
                        "name": "cursor",
                        "in": "query",
                        "schema": {
                            "type": "string"
                        }
                    },
                    {
                        "name": "since",
                        "in": "query",
                        "description": "sync_token from a previous full pass; returns changes and deletions only.",
                        "schema": {
                            "type": "string"
                        }
                    }
                ],
                "operationId": "getCategories",
                "description": "The category tree as the POS menu shows it (hidden groups and modifier groups are not categories). A full pass (no `since`) returns live objects ordered by last change; with `since` — only what changed after the token, deletions as `Deleted` tombstones. All pages of a pass see one consistent window, so an object edited during the pass is never lost: it arrives again in the next delta. Run a full pass at least daily as a reconciliation. A category hidden from the POS menu arrives as a tombstone."
            }
        },
        "/items": {
            "get": {
                "summary": "Items",
                "tags": [
                    "Catalog"
                ],
                "security": [
                    {
                        "oauth2": [
                            "catalog:read"
                        ]
                    },
                    {
                        "personalKey": []
                    }
                ],
                "x-palomapos-phase": "1a",
                "responses": {
                    "200": {
                        "description": "OK",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "type": "array",
                                            "items": {
                                                "oneOf": [
                                                    {
                                                        "$ref": "#/components/schemas/Item"
                                                    },
                                                    {
                                                        "$ref": "#/components/schemas/Deleted"
                                                    }
                                                ]
                                            }
                                        },
                                        "next_cursor": {
                                            "type": [
                                                "string",
                                                "null"
                                            ]
                                        },
                                        "sync_token": {
                                            "type": [
                                                "string",
                                                "null"
                                            ],
                                            "description": "null on every page but the last; on the last page pass it as `since` to receive only what changed afterwards (deletions included)."
                                        }
                                    },
                                    "required": [
                                        "data",
                                        "next_cursor",
                                        "sync_token"
                                    ]
                                },
                                "example": {
                                    "data": [
                                        {
                                            "id": "501",
                                            "name": "Cheeseburger",
                                            "description": "Beef patty, cheddar, pickles",
                                            "price": "12.50",
                                            "open_price": false,
                                            "currency": "USD",
                                            "category_id": "20",
                                            "sort_index": 1,
                                            "image_url": "https://cdn.example.com/items/cheeseburger.jpg",
                                            "barcodes": [
                                                "0123456789012"
                                            ],
                                            "sku": "BRG-01",
                                            "plu": null,
                                            "unit": "each",
                                            "tax_id": null,
                                            "effective_tax": {
                                                "tax_id": "1",
                                                "name": "Sales Tax",
                                                "rate": "8.875",
                                                "included": false
                                            },
                                            "modifier_group_ids": [
                                                "900"
                                            ],
                                            "available_for": {
                                                "pickup": true,
                                                "delivery": true
                                            },
                                            "deleted": false,
                                            "updated_at": "2026-09-29T08:20:00-04:00"
                                        },
                                        {
                                            "id": "514",
                                            "deleted": true,
                                            "updated_at": "2026-09-29T08:21:30-04:00"
                                        }
                                    ],
                                    "next_cursor": "eyJ2IjoxLCJ0IjoiYyIsInIiOiJpdGVtcyIsInAiOlsxNzkwMDAwMDAwLDUwMV19.RmFrZUN1cnNvclNpZw",
                                    "sync_token": null
                                }
                            }
                        },
                        "headers": {
                            "X-Request-Id": {
                                "$ref": "#/components/headers/X-Request-Id"
                            },
                            "PalomaPOS-Api-Version": {
                                "$ref": "#/components/headers/PalomaPOS-Api-Version"
                            }
                        }
                    },
                    "400": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                },
                                "example": {
                                    "error": {
                                        "code": "invalid_request",
                                        "message": "limit must be an integer between 1 and 200.",
                                        "retryable": false,
                                        "request_id": "req_4f1c2a9be07d5e8a1b3c6d20",
                                        "details": {
                                            "fields": {
                                                "limit": "out_of_range"
                                            }
                                        }
                                    }
                                }
                            }
                        },
                        "description": "invalid_request — limit, cursor or since is malformed, or was issued for another list",
                        "headers": {
                            "X-Request-Id": {
                                "$ref": "#/components/headers/X-Request-Id"
                            },
                            "PalomaPOS-Api-Version": {
                                "$ref": "#/components/headers/PalomaPOS-Api-Version"
                            }
                        }
                    },
                    "401": {
                        "description": "invalid_token",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                },
                                "example": {
                                    "error": {
                                        "code": "invalid_token",
                                        "message": "The access token is missing, expired or revoked.",
                                        "retryable": false,
                                        "request_id": "req_4f1c2a9be07d5e8a1b3c6d20",
                                        "details": {}
                                    }
                                }
                            }
                        },
                        "headers": {
                            "X-Request-Id": {
                                "$ref": "#/components/headers/X-Request-Id"
                            },
                            "PalomaPOS-Api-Version": {
                                "$ref": "#/components/headers/PalomaPOS-Api-Version"
                            }
                        }
                    },
                    "403": {
                        "description": "insufficient_scope / not_owner",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                },
                                "example": {
                                    "error": {
                                        "code": "insufficient_scope",
                                        "message": "The access token does not grant the scope required by this operation.",
                                        "retryable": false,
                                        "request_id": "req_4f1c2a9be07d5e8a1b3c6d20",
                                        "details": {
                                            "required_scope": "catalog:read"
                                        }
                                    }
                                }
                            }
                        },
                        "headers": {
                            "X-Request-Id": {
                                "$ref": "#/components/headers/X-Request-Id"
                            },
                            "PalomaPOS-Api-Version": {
                                "$ref": "#/components/headers/PalomaPOS-Api-Version"
                            }
                        }
                    },
                    "410": {
                        "description": "sync_token_expired — do a full pass",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                },
                                "example": {
                                    "error": {
                                        "code": "sync_token_expired",
                                        "message": "The sync_token is older than 20 days; deletions since then are no longer known. Do a full pass without since.",
                                        "retryable": false,
                                        "request_id": "req_4f1c2a9be07d5e8a1b3c6d20",
                                        "details": {
                                            "max_age_days": 20
                                        }
                                    }
                                }
                            }
                        },
                        "headers": {
                            "X-Request-Id": {
                                "$ref": "#/components/headers/X-Request-Id"
                            },
                            "PalomaPOS-Api-Version": {
                                "$ref": "#/components/headers/PalomaPOS-Api-Version"
                            }
                        }
                    },
                    "429": {
                        "description": "rate_limited",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                },
                                "example": {
                                    "error": {
                                        "code": "rate_limited",
                                        "message": "Rate limit exceeded: 600 read requests per minute for this app and account.",
                                        "retryable": true,
                                        "request_id": "req_4f1c2a9be07d5e8a1b3c6d20",
                                        "details": {
                                            "limit": 600,
                                            "kind": "read",
                                            "retry_after": 17
                                        }
                                    }
                                }
                            }
                        },
                        "headers": {
                            "Retry-After": {
                                "$ref": "#/components/headers/Retry-After"
                            },
                            "X-Request-Id": {
                                "$ref": "#/components/headers/X-Request-Id"
                            },
                            "PalomaPOS-Api-Version": {
                                "$ref": "#/components/headers/PalomaPOS-Api-Version"
                            }
                        }
                    },
                    "500": {
                        "$ref": "#/components/responses/InternalError"
                    },
                    "503": {
                        "$ref": "#/components/responses/Unavailable"
                    }
                },
                "parameters": [
                    {
                        "name": "limit",
                        "in": "query",
                        "schema": {
                            "type": "integer",
                            "minimum": 1,
                            "maximum": 200,
                            "default": 100
                        }
                    },
                    {
                        "name": "cursor",
                        "in": "query",
                        "schema": {
                            "type": "string"
                        }
                    },
                    {
                        "name": "since",
                        "in": "query",
                        "description": "sync_token from a previous full pass; returns changes and deletions only.",
                        "schema": {
                            "type": "string"
                        }
                    }
                ],
                "operationId": "getItems",
                "description": "Sellable items with the price the POS rings, barcodes, image, unit, modifier groups and the effective tax. A full pass (no `since`) returns live objects ordered by last change; with `since` — only what changed after the token, deletions as `Deleted` tombstones. All pages of a pass see one consistent window, so an object edited during the pass is never lost: it arrives again in the next delta. Run a full pass at least daily as a reconciliation. An item counts as changed when any of its parts changes: its row, barcodes, images, modifier-group links (its own or its category's), a linked group; a change of the account taxes re-sends every item."
            }
        },
        "/modifier-groups": {
            "get": {
                "summary": "Modifier groups with min/max and modifiers",
                "tags": [
                    "Catalog"
                ],
                "security": [
                    {
                        "oauth2": [
                            "catalog:read"
                        ]
                    },
                    {
                        "personalKey": []
                    }
                ],
                "x-palomapos-phase": "1a",
                "responses": {
                    "200": {
                        "description": "OK",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "type": "array",
                                            "items": {
                                                "oneOf": [
                                                    {
                                                        "$ref": "#/components/schemas/ModifierGroup"
                                                    },
                                                    {
                                                        "$ref": "#/components/schemas/Deleted"
                                                    }
                                                ]
                                            }
                                        },
                                        "next_cursor": {
                                            "type": [
                                                "string",
                                                "null"
                                            ]
                                        },
                                        "sync_token": {
                                            "type": [
                                                "string",
                                                "null"
                                            ],
                                            "description": "null on every page but the last; on the last page pass it as `since` to receive only what changed afterwards (deletions included)."
                                        }
                                    },
                                    "required": [
                                        "data",
                                        "next_cursor",
                                        "sync_token"
                                    ]
                                },
                                "example": {
                                    "data": [
                                        {
                                            "id": "900",
                                            "name": "Add-ons",
                                            "min_selected": 0,
                                            "max_selected": 3,
                                            "currency": "USD",
                                            "modifiers": [
                                                {
                                                    "id": "901",
                                                    "item_id": null,
                                                    "name": "Extra cheese",
                                                    "price": "1.25",
                                                    "is_default": false,
                                                    "max_quantity": 2,
                                                    "sort_index": 1
                                                },
                                                {
                                                    "id": "902",
                                                    "item_id": "530",
                                                    "name": "Bacon",
                                                    "price": "2.00",
                                                    "is_default": false,
                                                    "max_quantity": null,
                                                    "sort_index": 2
                                                }
                                            ],
                                            "deleted": false,
                                            "updated_at": "2026-09-29T08:18:00-04:00"
                                        }
                                    ],
                                    "next_cursor": null,
                                    "sync_token": "eyJ2IjoxLCJ0IjoicyIsInIiOiJpdGVtcyIsInciOjE3OTAwMDAwMDB9.Qm9ndXNTaWduYXR1cmU"
                                }
                            }
                        },
                        "headers": {
                            "X-Request-Id": {
                                "$ref": "#/components/headers/X-Request-Id"
                            },
                            "PalomaPOS-Api-Version": {
                                "$ref": "#/components/headers/PalomaPOS-Api-Version"
                            }
                        }
                    },
                    "400": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                },
                                "example": {
                                    "error": {
                                        "code": "invalid_request",
                                        "message": "limit must be an integer between 1 and 200.",
                                        "retryable": false,
                                        "request_id": "req_4f1c2a9be07d5e8a1b3c6d20",
                                        "details": {
                                            "fields": {
                                                "limit": "out_of_range"
                                            }
                                        }
                                    }
                                }
                            }
                        },
                        "description": "invalid_request — limit, cursor or since is malformed, or was issued for another list",
                        "headers": {
                            "X-Request-Id": {
                                "$ref": "#/components/headers/X-Request-Id"
                            },
                            "PalomaPOS-Api-Version": {
                                "$ref": "#/components/headers/PalomaPOS-Api-Version"
                            }
                        }
                    },
                    "401": {
                        "description": "invalid_token",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                },
                                "example": {
                                    "error": {
                                        "code": "invalid_token",
                                        "message": "The access token is missing, expired or revoked.",
                                        "retryable": false,
                                        "request_id": "req_4f1c2a9be07d5e8a1b3c6d20",
                                        "details": {}
                                    }
                                }
                            }
                        },
                        "headers": {
                            "X-Request-Id": {
                                "$ref": "#/components/headers/X-Request-Id"
                            },
                            "PalomaPOS-Api-Version": {
                                "$ref": "#/components/headers/PalomaPOS-Api-Version"
                            }
                        }
                    },
                    "403": {
                        "description": "insufficient_scope / not_owner",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                },
                                "example": {
                                    "error": {
                                        "code": "insufficient_scope",
                                        "message": "The access token does not grant the scope required by this operation.",
                                        "retryable": false,
                                        "request_id": "req_4f1c2a9be07d5e8a1b3c6d20",
                                        "details": {
                                            "required_scope": "catalog:read"
                                        }
                                    }
                                }
                            }
                        },
                        "headers": {
                            "X-Request-Id": {
                                "$ref": "#/components/headers/X-Request-Id"
                            },
                            "PalomaPOS-Api-Version": {
                                "$ref": "#/components/headers/PalomaPOS-Api-Version"
                            }
                        }
                    },
                    "410": {
                        "description": "sync_token_expired — do a full pass",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                },
                                "example": {
                                    "error": {
                                        "code": "sync_token_expired",
                                        "message": "The sync_token is older than 20 days; deletions since then are no longer known. Do a full pass without since.",
                                        "retryable": false,
                                        "request_id": "req_4f1c2a9be07d5e8a1b3c6d20",
                                        "details": {
                                            "max_age_days": 20
                                        }
                                    }
                                }
                            }
                        },
                        "headers": {
                            "X-Request-Id": {
                                "$ref": "#/components/headers/X-Request-Id"
                            },
                            "PalomaPOS-Api-Version": {
                                "$ref": "#/components/headers/PalomaPOS-Api-Version"
                            }
                        }
                    },
                    "429": {
                        "description": "rate_limited",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                },
                                "example": {
                                    "error": {
                                        "code": "rate_limited",
                                        "message": "Rate limit exceeded: 600 read requests per minute for this app and account.",
                                        "retryable": true,
                                        "request_id": "req_4f1c2a9be07d5e8a1b3c6d20",
                                        "details": {
                                            "limit": 600,
                                            "kind": "read",
                                            "retry_after": 17
                                        }
                                    }
                                }
                            }
                        },
                        "headers": {
                            "Retry-After": {
                                "$ref": "#/components/headers/Retry-After"
                            },
                            "X-Request-Id": {
                                "$ref": "#/components/headers/X-Request-Id"
                            },
                            "PalomaPOS-Api-Version": {
                                "$ref": "#/components/headers/PalomaPOS-Api-Version"
                            }
                        }
                    },
                    "500": {
                        "$ref": "#/components/responses/InternalError"
                    },
                    "503": {
                        "$ref": "#/components/responses/Unavailable"
                    }
                },
                "parameters": [
                    {
                        "name": "limit",
                        "in": "query",
                        "schema": {
                            "type": "integer",
                            "minimum": 1,
                            "maximum": 200,
                            "default": 100
                        }
                    },
                    {
                        "name": "cursor",
                        "in": "query",
                        "schema": {
                            "type": "string"
                        }
                    },
                    {
                        "name": "since",
                        "in": "query",
                        "description": "sync_token from a previous full pass; returns changes and deletions only.",
                        "schema": {
                            "type": "string"
                        }
                    }
                ],
                "operationId": "getModifierGroups",
                "description": "Modifier groups with their modifiers; modifier prices include the group surcharge. A full pass (no `since`) returns live objects ordered by last change; with `since` — only what changed after the token, deletions as `Deleted` tombstones. All pages of a pass see one consistent window, so an object edited during the pass is never lost: it arrives again in the next delta. Run a full pass at least daily as a reconciliation. A group counts as changed when it or any of its modifiers changes."
            }
        },
        "/menus": {
            "get": {
                "summary": "Menus, where they apply and what they contain",
                "tags": [
                    "Catalog"
                ],
                "security": [
                    {
                        "oauth2": [
                            "catalog:read"
                        ]
                    },
                    {
                        "personalKey": []
                    }
                ],
                "x-palomapos-phase": "1a",
                "responses": {
                    "200": {
                        "description": "OK",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "type": "array",
                                            "items": {
                                                "oneOf": [
                                                    {
                                                        "$ref": "#/components/schemas/Menu"
                                                    },
                                                    {
                                                        "$ref": "#/components/schemas/Deleted"
                                                    }
                                                ]
                                            }
                                        },
                                        "next_cursor": {
                                            "type": [
                                                "string",
                                                "null"
                                            ]
                                        },
                                        "sync_token": {
                                            "type": [
                                                "string",
                                                "null"
                                            ],
                                            "description": "null on every page but the last; on the last page pass it as `since` to receive only what changed afterwards (deletions included)."
                                        }
                                    },
                                    "required": [
                                        "data",
                                        "next_cursor",
                                        "sync_token"
                                    ]
                                },
                                "example": {
                                    "data": [
                                        {
                                            "id": "7",
                                            "name": "All day",
                                            "currency": "USD",
                                            "location_ids": [
                                                "3"
                                            ],
                                            "default_for_location_ids": [
                                                "3"
                                            ],
                                            "schedule": {
                                                "windows": [
                                                    {
                                                        "id": "3",
                                                        "name": "Lunch",
                                                        "days": [
                                                            "mon",
                                                            "tue",
                                                            "wed",
                                                            "thu",
                                                            "fri"
                                                        ],
                                                        "opens": "11:00:00",
                                                        "closes": "15:00:00",
                                                        "starts_on": null,
                                                        "ends_on": null,
                                                        "location_ids": [
                                                            "3"
                                                        ]
                                                    }
                                                ]
                                            },
                                            "entries": [
                                                {
                                                    "id": "70",
                                                    "parent_id": null,
                                                    "is_folder": true,
                                                    "item_id": null,
                                                    "name": "Burgers",
                                                    "price": null,
                                                    "open_price": false,
                                                    "sort_index": 1
                                                },
                                                {
                                                    "id": "71",
                                                    "parent_id": "70",
                                                    "is_folder": false,
                                                    "item_id": "501",
                                                    "name": "Cheeseburger",
                                                    "price": "12.50",
                                                    "open_price": false,
                                                    "sort_index": 1
                                                }
                                            ],
                                            "deleted": false,
                                            "updated_at": "2026-09-29T08:25:00-04:00"
                                        }
                                    ],
                                    "next_cursor": null,
                                    "sync_token": "eyJ2IjoxLCJ0IjoicyIsInIiOiJpdGVtcyIsInciOjE3OTAwMDAwMDB9.Qm9ndXNTaWduYXR1cmU"
                                }
                            }
                        },
                        "headers": {
                            "X-Request-Id": {
                                "$ref": "#/components/headers/X-Request-Id"
                            },
                            "PalomaPOS-Api-Version": {
                                "$ref": "#/components/headers/PalomaPOS-Api-Version"
                            }
                        }
                    },
                    "400": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                },
                                "example": {
                                    "error": {
                                        "code": "invalid_request",
                                        "message": "limit must be an integer between 1 and 200.",
                                        "retryable": false,
                                        "request_id": "req_4f1c2a9be07d5e8a1b3c6d20",
                                        "details": {
                                            "fields": {
                                                "limit": "out_of_range"
                                            }
                                        }
                                    }
                                }
                            }
                        },
                        "description": "invalid_request — location_id is not an id, or limit / cursor / since is malformed",
                        "headers": {
                            "X-Request-Id": {
                                "$ref": "#/components/headers/X-Request-Id"
                            },
                            "PalomaPOS-Api-Version": {
                                "$ref": "#/components/headers/PalomaPOS-Api-Version"
                            }
                        }
                    },
                    "401": {
                        "description": "invalid_token",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                },
                                "example": {
                                    "error": {
                                        "code": "invalid_token",
                                        "message": "The access token is missing, expired or revoked.",
                                        "retryable": false,
                                        "request_id": "req_4f1c2a9be07d5e8a1b3c6d20",
                                        "details": {}
                                    }
                                }
                            }
                        },
                        "headers": {
                            "X-Request-Id": {
                                "$ref": "#/components/headers/X-Request-Id"
                            },
                            "PalomaPOS-Api-Version": {
                                "$ref": "#/components/headers/PalomaPOS-Api-Version"
                            }
                        }
                    },
                    "403": {
                        "description": "insufficient_scope / not_owner",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                },
                                "example": {
                                    "error": {
                                        "code": "insufficient_scope",
                                        "message": "The access token does not grant the scope required by this operation.",
                                        "retryable": false,
                                        "request_id": "req_4f1c2a9be07d5e8a1b3c6d20",
                                        "details": {
                                            "required_scope": "catalog:read"
                                        }
                                    }
                                }
                            }
                        },
                        "headers": {
                            "X-Request-Id": {
                                "$ref": "#/components/headers/X-Request-Id"
                            },
                            "PalomaPOS-Api-Version": {
                                "$ref": "#/components/headers/PalomaPOS-Api-Version"
                            }
                        }
                    },
                    "410": {
                        "description": "sync_token_expired — do a full pass",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                },
                                "example": {
                                    "error": {
                                        "code": "sync_token_expired",
                                        "message": "The sync_token is older than 20 days; deletions since then are no longer known. Do a full pass without since.",
                                        "retryable": false,
                                        "request_id": "req_4f1c2a9be07d5e8a1b3c6d20",
                                        "details": {
                                            "max_age_days": 20
                                        }
                                    }
                                }
                            }
                        },
                        "headers": {
                            "X-Request-Id": {
                                "$ref": "#/components/headers/X-Request-Id"
                            },
                            "PalomaPOS-Api-Version": {
                                "$ref": "#/components/headers/PalomaPOS-Api-Version"
                            }
                        }
                    },
                    "429": {
                        "description": "rate_limited",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                },
                                "example": {
                                    "error": {
                                        "code": "rate_limited",
                                        "message": "Rate limit exceeded: 600 read requests per minute for this app and account.",
                                        "retryable": true,
                                        "request_id": "req_4f1c2a9be07d5e8a1b3c6d20",
                                        "details": {
                                            "limit": 600,
                                            "kind": "read",
                                            "retry_after": 17
                                        }
                                    }
                                }
                            }
                        },
                        "headers": {
                            "Retry-After": {
                                "$ref": "#/components/headers/Retry-After"
                            },
                            "X-Request-Id": {
                                "$ref": "#/components/headers/X-Request-Id"
                            },
                            "PalomaPOS-Api-Version": {
                                "$ref": "#/components/headers/PalomaPOS-Api-Version"
                            }
                        }
                    },
                    "500": {
                        "$ref": "#/components/responses/InternalError"
                    },
                    "503": {
                        "$ref": "#/components/responses/Unavailable"
                    }
                },
                "parameters": [
                    {
                        "name": "limit",
                        "in": "query",
                        "schema": {
                            "type": "integer",
                            "minimum": 1,
                            "maximum": 200,
                            "default": 100
                        }
                    },
                    {
                        "name": "cursor",
                        "in": "query",
                        "schema": {
                            "type": "string"
                        }
                    },
                    {
                        "name": "since",
                        "in": "query",
                        "description": "sync_token from a previous full pass; returns changes and deletions only.",
                        "schema": {
                            "type": "string"
                        }
                    },
                    {
                        "name": "location_id",
                        "in": "query",
                        "schema": {
                            "type": "string"
                        },
                        "description": "Only menus that can apply at this location (Location.id)."
                    }
                ],
                "operationId": "getMenus",
                "description": "Menus with entries, schedule windows and locations. A full pass (no `since`) returns live objects ordered by last change; with `since` — only what changed after the token, deletions as `Deleted` tombstones. All pages of a pass see one consistent window, so an object edited during the pass is never lost: it arrives again in the next delta. Run a full pass at least daily as a reconciliation. With `location_id` — only menus that can apply at that location; in a delta a menu that stopped applying there arrives as a tombstone. Cursors and sync tokens with and without the filter are different lists and are not interchangeable. With the filter a page may hold fewer menus than `limit` — even none — while `next_cursor` is set: keep following it until it is null."
            }
        },
        "/locations/{id}/stop-list": {
            "get": {
                "summary": "What is not for sale right now",
                "tags": [
                    "Catalog"
                ],
                "security": [
                    {
                        "oauth2": [
                            "catalog:read"
                        ]
                    },
                    {
                        "personalKey": []
                    }
                ],
                "x-palomapos-phase": "1a",
                "responses": {
                    "200": {
                        "description": "OK",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/StopList"
                                },
                                "example": {
                                    "location_id": "3",
                                    "as_of": "2026-09-29T17:50:00-04:00",
                                    "data": [
                                        {
                                            "item_id": "503",
                                            "until": "2026-09-29T23:59:59-04:00",
                                            "source": "manual"
                                        }
                                    ],
                                    "limited": [
                                        {
                                            "item_id": "504",
                                            "remaining_quantity": "3",
                                            "until": null
                                        }
                                    ]
                                }
                            }
                        },
                        "headers": {
                            "X-Request-Id": {
                                "$ref": "#/components/headers/X-Request-Id"
                            },
                            "PalomaPOS-Api-Version": {
                                "$ref": "#/components/headers/PalomaPOS-Api-Version"
                            }
                        }
                    },
                    "401": {
                        "description": "invalid_token",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                },
                                "example": {
                                    "error": {
                                        "code": "invalid_token",
                                        "message": "The access token is missing, expired or revoked.",
                                        "retryable": false,
                                        "request_id": "req_4f1c2a9be07d5e8a1b3c6d20",
                                        "details": {}
                                    }
                                }
                            }
                        },
                        "headers": {
                            "X-Request-Id": {
                                "$ref": "#/components/headers/X-Request-Id"
                            },
                            "PalomaPOS-Api-Version": {
                                "$ref": "#/components/headers/PalomaPOS-Api-Version"
                            }
                        }
                    },
                    "403": {
                        "description": "insufficient_scope / not_owner",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                },
                                "example": {
                                    "error": {
                                        "code": "insufficient_scope",
                                        "message": "The access token does not grant the scope required by this operation.",
                                        "retryable": false,
                                        "request_id": "req_4f1c2a9be07d5e8a1b3c6d20",
                                        "details": {
                                            "required_scope": "catalog:read"
                                        }
                                    }
                                }
                            }
                        },
                        "headers": {
                            "X-Request-Id": {
                                "$ref": "#/components/headers/X-Request-Id"
                            },
                            "PalomaPOS-Api-Version": {
                                "$ref": "#/components/headers/PalomaPOS-Api-Version"
                            }
                        }
                    },
                    "404": {
                        "description": "not_found",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                },
                                "example": {
                                    "error": {
                                        "code": "not_found",
                                        "message": "There is no such location in this account.",
                                        "retryable": false,
                                        "request_id": "req_4f1c2a9be07d5e8a1b3c6d20",
                                        "details": {}
                                    }
                                }
                            }
                        },
                        "headers": {
                            "X-Request-Id": {
                                "$ref": "#/components/headers/X-Request-Id"
                            },
                            "PalomaPOS-Api-Version": {
                                "$ref": "#/components/headers/PalomaPOS-Api-Version"
                            }
                        }
                    },
                    "429": {
                        "description": "rate_limited",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                },
                                "example": {
                                    "error": {
                                        "code": "rate_limited",
                                        "message": "Rate limit exceeded: 600 read requests per minute for this app and account.",
                                        "retryable": true,
                                        "request_id": "req_4f1c2a9be07d5e8a1b3c6d20",
                                        "details": {
                                            "limit": 600,
                                            "kind": "read",
                                            "retry_after": 17
                                        }
                                    }
                                }
                            }
                        },
                        "headers": {
                            "Retry-After": {
                                "$ref": "#/components/headers/Retry-After"
                            },
                            "X-Request-Id": {
                                "$ref": "#/components/headers/X-Request-Id"
                            },
                            "PalomaPOS-Api-Version": {
                                "$ref": "#/components/headers/PalomaPOS-Api-Version"
                            }
                        }
                    },
                    "500": {
                        "$ref": "#/components/responses/InternalError"
                    },
                    "503": {
                        "$ref": "#/components/responses/Unavailable"
                    }
                },
                "parameters": [
                    {
                        "name": "id",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "string"
                        }
                    }
                ],
                "operationId": "getLocationsStopList",
                "description": "What is not for sale at the location right now and until when, plus items on sale with a limited remaining quantity. `404` when the location does not exist in this account."
            }
        },
        "/orders/quote": {
            "post": {
                "summary": "Price a cart without creating an order",
                "tags": [
                    "Orders"
                ],
                "security": [
                    {
                        "oauth2": [
                            "orders:write"
                        ]
                    },
                    {
                        "personalKey": []
                    }
                ],
                "x-palomapos-phase": "3",
                "responses": {
                    "200": {
                        "description": "OK",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Quote"
                                },
                                "example": {
                                    "currency": "USD",
                                    "lines": [
                                        {
                                            "item_id": "501",
                                            "name": "Cheeseburger",
                                            "quantity": "2",
                                            "unit_price": "12.50",
                                            "modifiers": [
                                                {
                                                    "modifier_id": "901",
                                                    "name": "Extra cheese",
                                                    "quantity": "2",
                                                    "unit_price": "1.25",
                                                    "total": "2.50"
                                                }
                                            ],
                                            "modifiers_total": "2.50",
                                            "subtotal": "27.50",
                                            "taxes": [
                                                {
                                                    "tax_id": "1",
                                                    "name": "Sales Tax",
                                                    "amount": "2.44",
                                                    "included": false,
                                                    "rate": "8.875"
                                                }
                                            ],
                                            "note": "No onions"
                                        }
                                    ],
                                    "subtotal": "27.50",
                                    "tax_total": "2.44",
                                    "taxes": [
                                        {
                                            "tax_id": "1",
                                            "name": "Sales Tax",
                                            "amount": "2.44",
                                            "included": false
                                        }
                                    ],
                                    "fees": [],
                                    "taxes_included_in_prices": false,
                                    "delivery_fee": "5.00",
                                    "tip": "3.00",
                                    "total": "34.94",
                                    "total_with_tip": "37.94"
                                }
                            }
                        },
                        "headers": {
                            "X-Request-Id": {
                                "$ref": "#/components/headers/X-Request-Id"
                            },
                            "PalomaPOS-Api-Version": {
                                "$ref": "#/components/headers/PalomaPOS-Api-Version"
                            }
                        }
                    },
                    "400": {
                        "description": "invalid_request — details.fields",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                },
                                "examples": {
                                    "invalid_request": {
                                        "summary": "invalid_request",
                                        "value": {
                                            "error": {
                                                "code": "invalid_request",
                                                "message": "The request body is invalid: see details.fields.",
                                                "retryable": false,
                                                "request_id": "req_4f1c2a9be07d5e8a1b3c6d20",
                                                "details": {
                                                    "fields": {
                                                        "lines[0].quantity": "invalid",
                                                        "customer.phone": "invalid"
                                                    }
                                                }
                                            }
                                        }
                                    },
                                    "unknown_location": {
                                        "summary": "invalid_request — unknown location",
                                        "value": {
                                            "error": {
                                                "code": "invalid_request",
                                                "message": "There is no such location in this account.",
                                                "retryable": false,
                                                "request_id": "req_4f1c2a9be07d5e8a1b3c6d20",
                                                "details": {
                                                    "fields": {
                                                        "location_id": "unknown"
                                                    }
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        },
                        "headers": {
                            "X-Request-Id": {
                                "$ref": "#/components/headers/X-Request-Id"
                            },
                            "PalomaPOS-Api-Version": {
                                "$ref": "#/components/headers/PalomaPOS-Api-Version"
                            }
                        }
                    },
                    "401": {
                        "description": "invalid_token",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                },
                                "example": {
                                    "error": {
                                        "code": "invalid_token",
                                        "message": "The access token is missing, expired or revoked.",
                                        "retryable": false,
                                        "request_id": "req_4f1c2a9be07d5e8a1b3c6d20",
                                        "details": {}
                                    }
                                }
                            }
                        },
                        "headers": {
                            "X-Request-Id": {
                                "$ref": "#/components/headers/X-Request-Id"
                            },
                            "PalomaPOS-Api-Version": {
                                "$ref": "#/components/headers/PalomaPOS-Api-Version"
                            }
                        }
                    },
                    "403": {
                        "description": "insufficient_scope (orders:write)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                },
                                "example": {
                                    "error": {
                                        "code": "insufficient_scope",
                                        "message": "The access token does not grant the scope required by this operation.",
                                        "retryable": false,
                                        "request_id": "req_4f1c2a9be07d5e8a1b3c6d20",
                                        "details": {
                                            "required_scope": "orders:write"
                                        }
                                    }
                                }
                            }
                        },
                        "headers": {
                            "X-Request-Id": {
                                "$ref": "#/components/headers/X-Request-Id"
                            },
                            "PalomaPOS-Api-Version": {
                                "$ref": "#/components/headers/PalomaPOS-Api-Version"
                            }
                        }
                    },
                    "404": {
                        "description": "not_found — the orders flag is off",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                },
                                "example": {
                                    "error": {
                                        "code": "not_found",
                                        "message": "The requested object does not exist in this account.",
                                        "retryable": false,
                                        "request_id": "req_4f1c2a9be07d5e8a1b3c6d20",
                                        "details": {}
                                    }
                                }
                            }
                        },
                        "headers": {
                            "X-Request-Id": {
                                "$ref": "#/components/headers/X-Request-Id"
                            },
                            "PalomaPOS-Api-Version": {
                                "$ref": "#/components/headers/PalomaPOS-Api-Version"
                            }
                        }
                    },
                    "422": {
                        "description": "item_unavailable / fulfillment_disabled / quote_unsupported (details.reason) — see POST /orders",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                },
                                "examples": {
                                    "quote_unsupported": {
                                        "summary": "quote_unsupported — dual_pricing",
                                        "value": {
                                            "error": {
                                                "code": "quote_unsupported",
                                                "message": "The location applies dual pricing (card surcharge or cash discount); the total depends on how the guest pays.",
                                                "retryable": false,
                                                "request_id": "req_4f1c2a9be07d5e8a1b3c6d20",
                                                "details": {
                                                    "reason": "dual_pricing"
                                                }
                                            }
                                        }
                                    },
                                    "item_unavailable": {
                                        "summary": "item_unavailable — stop_list",
                                        "value": {
                                            "error": {
                                                "code": "item_unavailable",
                                                "message": "Item 503 is out of stock at this location.",
                                                "retryable": false,
                                                "request_id": "req_4f1c2a9be07d5e8a1b3c6d20",
                                                "details": {
                                                    "item_id": "503",
                                                    "reason": "stop_list"
                                                }
                                            }
                                        }
                                    },
                                    "pos_not_supported": {
                                        "summary": "fulfillment_disabled — pos_not_supported",
                                        "value": {
                                            "error": {
                                                "code": "fulfillment_disabled",
                                                "message": "This account runs a POS that cannot receive orders through the API.",
                                                "retryable": false,
                                                "request_id": "req_4f1c2a9be07d5e8a1b3c6d20",
                                                "details": {
                                                    "reason": "pos_not_supported"
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        },
                        "headers": {
                            "X-Request-Id": {
                                "$ref": "#/components/headers/X-Request-Id"
                            },
                            "PalomaPOS-Api-Version": {
                                "$ref": "#/components/headers/PalomaPOS-Api-Version"
                            }
                        }
                    },
                    "429": {
                        "description": "rate_limited",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                },
                                "example": {
                                    "error": {
                                        "code": "rate_limited",
                                        "message": "Rate limit exceeded: 60 write requests per minute for this app and account.",
                                        "retryable": true,
                                        "request_id": "req_4f1c2a9be07d5e8a1b3c6d20",
                                        "details": {
                                            "limit": 60,
                                            "kind": "write",
                                            "retry_after": 23
                                        }
                                    }
                                }
                            }
                        },
                        "headers": {
                            "Retry-After": {
                                "$ref": "#/components/headers/Retry-After"
                            },
                            "X-Request-Id": {
                                "$ref": "#/components/headers/X-Request-Id"
                            },
                            "PalomaPOS-Api-Version": {
                                "$ref": "#/components/headers/PalomaPOS-Api-Version"
                            }
                        }
                    },
                    "500": {
                        "$ref": "#/components/responses/InternalError"
                    },
                    "503": {
                        "$ref": "#/components/responses/Unavailable"
                    }
                },
                "description": "Prices a cart without creating anything — the same function and the same checks as POST /orders (except the delivery address; expected_total is ignored). Answers 422 quote_unsupported with details.reason instead of a total the POS might not book: discounts the POS would apply to the guest, dual pricing / card surcharge, automatic fees for the order type, automatic service charge, automatic promotions, an ambiguous default tax, time prices, combos, non-retail price types, menu prices that differ from the catalog, open prices. No Idempotency-Key needed; it is a POST, so it counts against the write rate limit and is recorded in the app's write log.",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/OrderInput"
                            },
                            "example": {
                                "location_id": "3",
                                "fulfillment": {
                                    "type": "delivery",
                                    "asap": true
                                },
                                "delivery_address": {
                                    "formatted": "200 Sample St, Apt 4, Miami, FL 33101"
                                },
                                "lines": [
                                    {
                                        "item_id": "501",
                                        "quantity": "2",
                                        "modifiers": [
                                            {
                                                "modifier_id": "901"
                                            }
                                        ],
                                        "note": "No onions"
                                    }
                                ],
                                "tip": {
                                    "amount": "3.00"
                                }
                            }
                        }
                    }
                },
                "operationId": "postOrdersQuote"
            }
        },
        "/orders": {
            "post": {
                "summary": "Create an order",
                "tags": [
                    "Orders"
                ],
                "security": [
                    {
                        "oauth2": [
                            "orders:write"
                        ]
                    },
                    {
                        "personalKey": []
                    }
                ],
                "x-palomapos-phase": "2",
                "responses": {
                    "200": {
                        "description": "The order — created now, found again for the same Idempotency-Key and body, or the stored response (header Idempotent-Replayed: true). Same object as GET /orders/{id}.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Order"
                                },
                                "example": {
                                    "id": "10432",
                                    "number": "42",
                                    "location_id": "3",
                                    "deleted": false,
                                    "source": {
                                        "app_client_id": "ppc_0123456789abcdef0123456789abcdef",
                                        "name": "Example Orders App",
                                        "external_id": "ord-8812"
                                    },
                                    "status": "new",
                                    "fulfillment": {
                                        "type": "pickup",
                                        "asap": false,
                                        "ready_at": "2026-09-29T18:30:00-04:00"
                                    },
                                    "customer": {
                                        "id": null,
                                        "name": null,
                                        "phone": "+13055550100"
                                    },
                                    "delivery_address": null,
                                    "note": "Ring the bell",
                                    "lines": [
                                        {
                                            "id": "90001",
                                            "item_id": "501",
                                            "name": "Cheeseburger",
                                            "quantity": "2",
                                            "unit_price": "12.50",
                                            "modifiers": [
                                                {
                                                    "id": "90002",
                                                    "modifier_id": "901",
                                                    "name": "Extra cheese",
                                                    "quantity": "2",
                                                    "unit_price": "1.25",
                                                    "total": "2.50"
                                                }
                                            ],
                                            "modifiers_total": "2.50",
                                            "subtotal": "27.50",
                                            "discount_total": "0.00",
                                            "taxes": [
                                                {
                                                    "tax_id": "1",
                                                    "name": "Sales Tax",
                                                    "amount": "2.44",
                                                    "included": false,
                                                    "rate": "8.875"
                                                }
                                            ],
                                            "note": "No onions"
                                        }
                                    ],
                                    "currency": "USD",
                                    "subtotal": "27.50",
                                    "discount_total": "0.00",
                                    "service_charge": "0.00",
                                    "tax_total": "2.44",
                                    "taxes": [
                                        {
                                            "tax_id": "1",
                                            "name": "Sales Tax",
                                            "amount": "2.44",
                                            "included": false
                                        }
                                    ],
                                    "fees": [],
                                    "taxes_included_in_prices": false,
                                    "delivery_fee": "0.00",
                                    "tip": "3.00",
                                    "total": "29.94",
                                    "paid": false,
                                    "payments": [],
                                    "cancel_reason": null,
                                    "created_at": "2026-09-29T17:52:10-04:00",
                                    "updated_at": "2026-09-29T17:52:10-04:00",
                                    "closed_at": null
                                }
                            }
                        },
                        "headers": {
                            "X-Request-Id": {
                                "$ref": "#/components/headers/X-Request-Id"
                            },
                            "PalomaPOS-Api-Version": {
                                "$ref": "#/components/headers/PalomaPOS-Api-Version"
                            },
                            "Idempotent-Replayed": {
                                "$ref": "#/components/headers/Idempotent-Replayed"
                            }
                        }
                    },
                    "400": {
                        "description": "invalid_request — details.fields (e.g. lines[0].quantity must_be_whole_for_item_not_sold_by_weight, lines[0].modifiers group_12_requires_at_least_1, delivery_address required_for_delivery, location_id unknown, tip.amount exceeds_order_amount, Idempotency-Key required)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                },
                                "examples": {
                                    "invalid_request": {
                                        "summary": "invalid_request",
                                        "value": {
                                            "error": {
                                                "code": "invalid_request",
                                                "message": "The request body is invalid: see details.fields.",
                                                "retryable": false,
                                                "request_id": "req_4f1c2a9be07d5e8a1b3c6d20",
                                                "details": {
                                                    "fields": {
                                                        "lines[0].quantity": "invalid",
                                                        "customer.phone": "invalid"
                                                    }
                                                }
                                            }
                                        }
                                    },
                                    "unknown_location": {
                                        "summary": "invalid_request — unknown location",
                                        "value": {
                                            "error": {
                                                "code": "invalid_request",
                                                "message": "There is no such location in this account.",
                                                "retryable": false,
                                                "request_id": "req_4f1c2a9be07d5e8a1b3c6d20",
                                                "details": {
                                                    "fields": {
                                                        "location_id": "unknown"
                                                    }
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        },
                        "headers": {
                            "X-Request-Id": {
                                "$ref": "#/components/headers/X-Request-Id"
                            },
                            "PalomaPOS-Api-Version": {
                                "$ref": "#/components/headers/PalomaPOS-Api-Version"
                            }
                        }
                    },
                    "401": {
                        "description": "invalid_token",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                },
                                "example": {
                                    "error": {
                                        "code": "invalid_token",
                                        "message": "The access token is missing, expired or revoked.",
                                        "retryable": false,
                                        "request_id": "req_4f1c2a9be07d5e8a1b3c6d20",
                                        "details": {}
                                    }
                                }
                            }
                        },
                        "headers": {
                            "X-Request-Id": {
                                "$ref": "#/components/headers/X-Request-Id"
                            },
                            "PalomaPOS-Api-Version": {
                                "$ref": "#/components/headers/PalomaPOS-Api-Version"
                            }
                        }
                    },
                    "403": {
                        "description": "insufficient_scope (orders:write)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                },
                                "example": {
                                    "error": {
                                        "code": "insufficient_scope",
                                        "message": "The access token does not grant the scope required by this operation.",
                                        "retryable": false,
                                        "request_id": "req_4f1c2a9be07d5e8a1b3c6d20",
                                        "details": {
                                            "required_scope": "orders:write"
                                        }
                                    }
                                }
                            }
                        },
                        "headers": {
                            "X-Request-Id": {
                                "$ref": "#/components/headers/X-Request-Id"
                            },
                            "PalomaPOS-Api-Version": {
                                "$ref": "#/components/headers/PalomaPOS-Api-Version"
                            }
                        }
                    },
                    "404": {
                        "description": "not_found — the orders flag (PLATFORM_API_ORDERS_ENABLED) is off on this host",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                },
                                "example": {
                                    "error": {
                                        "code": "not_found",
                                        "message": "The requested object does not exist in this account.",
                                        "retryable": false,
                                        "request_id": "req_4f1c2a9be07d5e8a1b3c6d20",
                                        "details": {}
                                    }
                                }
                            }
                        },
                        "headers": {
                            "X-Request-Id": {
                                "$ref": "#/components/headers/X-Request-Id"
                            },
                            "PalomaPOS-Api-Version": {
                                "$ref": "#/components/headers/PalomaPOS-Api-Version"
                            }
                        }
                    },
                    "409": {
                        "description": "idempotency_key_reused (also when this key already created an order from a different body within 24 h) / idempotency_in_progress (retryable, Retry-After) / total_mismatch — details: expected, actual (Money), quote (Quote); nothing is created",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                },
                                "examples": {
                                    "total_mismatch": {
                                        "summary": "total_mismatch",
                                        "value": {
                                            "error": {
                                                "code": "total_mismatch",
                                                "message": "The order total computed by PalomaPOS differs from expected_total. Nothing was created.",
                                                "retryable": false,
                                                "request_id": "req_4f1c2a9be07d5e8a1b3c6d20",
                                                "details": {
                                                    "expected": "29.90",
                                                    "actual": "29.94",
                                                    "quote": {
                                                        "currency": "USD",
                                                        "lines": [
                                                            {
                                                                "item_id": "501",
                                                                "name": "Cheeseburger",
                                                                "quantity": "2",
                                                                "unit_price": "12.50",
                                                                "modifiers": [
                                                                    {
                                                                        "modifier_id": "901",
                                                                        "name": "Extra cheese",
                                                                        "quantity": "2",
                                                                        "unit_price": "1.25",
                                                                        "total": "2.50"
                                                                    }
                                                                ],
                                                                "modifiers_total": "2.50",
                                                                "subtotal": "27.50",
                                                                "taxes": [
                                                                    {
                                                                        "tax_id": "1",
                                                                        "name": "Sales Tax",
                                                                        "amount": "2.44",
                                                                        "included": false,
                                                                        "rate": "8.875"
                                                                    }
                                                                ],
                                                                "note": "No onions"
                                                            }
                                                        ],
                                                        "subtotal": "27.50",
                                                        "tax_total": "2.44",
                                                        "taxes": [
                                                            {
                                                                "tax_id": "1",
                                                                "name": "Sales Tax",
                                                                "amount": "2.44",
                                                                "included": false
                                                            }
                                                        ],
                                                        "fees": [],
                                                        "taxes_included_in_prices": false,
                                                        "delivery_fee": "5.00",
                                                        "tip": "3.00",
                                                        "total": "34.94",
                                                        "total_with_tip": "37.94"
                                                    }
                                                }
                                            }
                                        }
                                    },
                                    "idempotency_key_reused": {
                                        "summary": "idempotency_key_reused",
                                        "value": {
                                            "error": {
                                                "code": "idempotency_key_reused",
                                                "message": "This Idempotency-Key was already used with a different request. Use a new key for a new request.",
                                                "retryable": false,
                                                "request_id": "req_4f1c2a9be07d5e8a1b3c6d20",
                                                "details": {}
                                            }
                                        }
                                    },
                                    "idempotency_in_progress": {
                                        "summary": "idempotency_in_progress",
                                        "value": {
                                            "error": {
                                                "code": "idempotency_in_progress",
                                                "message": "A request with this Idempotency-Key is still being processed. Retry with the same key shortly.",
                                                "retryable": true,
                                                "request_id": "req_4f1c2a9be07d5e8a1b3c6d20",
                                                "details": {}
                                            }
                                        }
                                    }
                                }
                            }
                        },
                        "headers": {
                            "X-Request-Id": {
                                "$ref": "#/components/headers/X-Request-Id"
                            },
                            "PalomaPOS-Api-Version": {
                                "$ref": "#/components/headers/PalomaPOS-Api-Version"
                            },
                            "Retry-After": {
                                "$ref": "#/components/headers/Retry-After",
                                "description": "Only with `idempotency_in_progress`."
                            }
                        }
                    },
                    "422": {
                        "description": "item_unavailable — details.item_id, details.reason: not_found | not_available_for_fulfillment | stop_list | stop_list_limit (details.available) | not_on_menu; fulfillment_disabled — details.reason: disabled | below_minimum (details.min_order_amount, details.subtotal) | pos_not_supported; quote_unsupported — details.reason (the same as POST /orders/quote): time_price | combo | price_type | menu_price | open_price | negative_line | amount_out_of_range | unparseable_number | discount | dual_pricing | order_type_charge | service_charge | ambiguous_default_tax | automatic_promotion",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                },
                                "examples": {
                                    "quote_unsupported": {
                                        "summary": "quote_unsupported — dual_pricing",
                                        "value": {
                                            "error": {
                                                "code": "quote_unsupported",
                                                "message": "The location applies dual pricing (card surcharge or cash discount); the total depends on how the guest pays.",
                                                "retryable": false,
                                                "request_id": "req_4f1c2a9be07d5e8a1b3c6d20",
                                                "details": {
                                                    "reason": "dual_pricing"
                                                }
                                            }
                                        }
                                    },
                                    "item_unavailable": {
                                        "summary": "item_unavailable — stop_list",
                                        "value": {
                                            "error": {
                                                "code": "item_unavailable",
                                                "message": "Item 503 is out of stock at this location.",
                                                "retryable": false,
                                                "request_id": "req_4f1c2a9be07d5e8a1b3c6d20",
                                                "details": {
                                                    "item_id": "503",
                                                    "reason": "stop_list"
                                                }
                                            }
                                        }
                                    },
                                    "pos_not_supported": {
                                        "summary": "fulfillment_disabled — pos_not_supported",
                                        "value": {
                                            "error": {
                                                "code": "fulfillment_disabled",
                                                "message": "This account runs a POS that cannot receive orders through the API.",
                                                "retryable": false,
                                                "request_id": "req_4f1c2a9be07d5e8a1b3c6d20",
                                                "details": {
                                                    "reason": "pos_not_supported"
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        },
                        "headers": {
                            "X-Request-Id": {
                                "$ref": "#/components/headers/X-Request-Id"
                            },
                            "PalomaPOS-Api-Version": {
                                "$ref": "#/components/headers/PalomaPOS-Api-Version"
                            }
                        }
                    },
                    "429": {
                        "description": "rate_limited",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                },
                                "example": {
                                    "error": {
                                        "code": "rate_limited",
                                        "message": "Rate limit exceeded: 60 write requests per minute for this app and account.",
                                        "retryable": true,
                                        "request_id": "req_4f1c2a9be07d5e8a1b3c6d20",
                                        "details": {
                                            "limit": 60,
                                            "kind": "write",
                                            "retry_after": 23
                                        }
                                    }
                                }
                            }
                        },
                        "headers": {
                            "Retry-After": {
                                "$ref": "#/components/headers/Retry-After"
                            },
                            "X-Request-Id": {
                                "$ref": "#/components/headers/X-Request-Id"
                            },
                            "PalomaPOS-Api-Version": {
                                "$ref": "#/components/headers/PalomaPOS-Api-Version"
                            }
                        }
                    },
                    "500": {
                        "$ref": "#/components/responses/InternalError"
                    },
                    "503": {
                        "description": "temporarily_unavailable — the order-number counter or this key is busy; retry with the same Idempotency-Key (Retry-After) · or `account_not_ready` (not retryable): this business account's database has not been upgraded for the API yet",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                },
                                "example": {
                                    "error": {
                                        "code": "temporarily_unavailable",
                                        "message": "The order number counter is busy. Retry with the same Idempotency-Key.",
                                        "retryable": true,
                                        "request_id": "req_4f1c2a9be07d5e8a1b3c6d20",
                                        "details": {}
                                    }
                                }
                            }
                        },
                        "headers": {
                            "Retry-After": {
                                "$ref": "#/components/headers/Retry-After"
                            },
                            "X-Request-Id": {
                                "$ref": "#/components/headers/X-Request-Id"
                            },
                            "PalomaPOS-Api-Version": {
                                "$ref": "#/components/headers/PalomaPOS-Api-Version"
                            }
                        }
                    }
                },
                "description": "Creates a pickup or delivery order on behalf of the app (the source comes from the token: d_order_delivery.source_name = the app's display name, foreign_system_name = its key). The POS gets it through the account socket like online-ordering orders; the order number (`number`, d_order.idout) comes from the shared POS counter. Unit prices are what the cashier would ring at this location now (the location's pinned menu, otherwise the catalog price); carts whose price the server cannot know — a time price active now or at ready_at, a combo, a non-retail price type of the location, an open price, a menu price differing from the catalog while no menu is pinned — are refused with 422 quote_unsupported. Pricing uses the POS v2 formula (same function as /orders/quote): the order stores per-line taxes in the POS format and `total`. Every order is created priced: a cart the server cannot price exactly — the unit-price reasons above, or an order-level reason (dual pricing, automatic fees or service charge, automatic promotions, a customer discount the POS would apply, an ambiguous default tax) — is refused with the same 422 quote_unsupported as POST /orders/quote, and nothing is written. The POS takes an API order's lines, taxes and total as written and never re-prices it. With `expected_total` the order is created only if the totals match. Checks: location of the account, mode on for the location, items sold for this mode (not deleted, not in the stop list, within its remaining count), modifier rules, minimum order amount, tip ≤ subtotal. Idempotency: besides the stored response, a retry within the key's 24 hours after a crash finds the already written order by the key and never duplicates it; the same key with a different body within 24 h is 409 idempotency_key_reused even when the stored response was lost (the key was released by a 5xx after the order was written). After 24 h a key is new again, with any body. Accounts on the legacy Windows POS cannot receive API orders: 422 fulfillment_disabled (reason pos_not_supported).",
                "parameters": [
                    {
                        "name": "Idempotency-Key",
                        "in": "header",
                        "required": true,
                        "schema": {
                            "type": "string",
                            "maxLength": 64
                        },
                        "description": "Required. 1–64 printable ASCII characters, case-sensitive, scoped to the app and account, kept 24 h. The same key with the same request (method, path, query, JSON body regardless of key order and whitespace) returns the stored response with header `Idempotent-Replayed: true`; with a different request — 409 idempotency_key_reused. While the first request with this key is still running — 409 idempotency_in_progress (retryable, Retry-After: 1). Responses to 400, 429 and 5xx are not stored: retrying with the same key runs the operation again."
                    }
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/OrderInput"
                            },
                            "example": {
                                "location_id": "3",
                                "fulfillment": {
                                    "type": "pickup",
                                    "ready_at": "2026-09-29T18:30:00-04:00"
                                },
                                "customer": {
                                    "name": "Sam Guest",
                                    "phone": "+13055550100"
                                },
                                "note": "Ring the bell",
                                "lines": [
                                    {
                                        "item_id": "501",
                                        "quantity": "2",
                                        "modifiers": [
                                            {
                                                "modifier_id": "901"
                                            }
                                        ],
                                        "note": "No onions"
                                    }
                                ],
                                "tip": {
                                    "amount": "3.00"
                                },
                                "external_id": "ord-8812",
                                "expected_total": "29.94"
                            }
                        }
                    }
                },
                "operationId": "postOrders"
            },
            "get": {
                "summary": "Orders of the account (all sources)",
                "tags": [
                    "Orders"
                ],
                "security": [
                    {
                        "oauth2": [
                            "orders:read"
                        ]
                    },
                    {
                        "personalKey": []
                    }
                ],
                "x-palomapos-phase": "1b",
                "responses": {
                    "200": {
                        "description": "OK",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "type": "array",
                                            "items": {
                                                "$ref": "#/components/schemas/Order"
                                            }
                                        },
                                        "next_cursor": {
                                            "type": [
                                                "string",
                                                "null"
                                            ]
                                        },
                                        "sync_token": {
                                            "type": [
                                                "string",
                                                "null"
                                            ],
                                            "description": "null on every page but the last; on the last page pass it as `since` to receive only what changed afterwards (deletions included)."
                                        }
                                    },
                                    "required": [
                                        "data",
                                        "next_cursor",
                                        "sync_token"
                                    ]
                                },
                                "example": {
                                    "data": [
                                        {
                                            "id": "10429",
                                            "number": "39",
                                            "location_id": "3",
                                            "deleted": false,
                                            "source": {
                                                "app_client_id": null,
                                                "name": null,
                                                "external_id": null
                                            },
                                            "status": "completed",
                                            "fulfillment": {
                                                "type": "dine_in",
                                                "asap": null,
                                                "ready_at": null
                                            },
                                            "customer": {
                                                "id": "77",
                                                "name": null,
                                                "phone": null
                                            },
                                            "delivery_address": null,
                                            "note": null,
                                            "lines": [
                                                {
                                                    "id": "89990",
                                                    "item_id": "502",
                                                    "name": "Fries",
                                                    "quantity": "1",
                                                    "unit_price": "4.99",
                                                    "modifiers": [],
                                                    "modifiers_total": "0.00",
                                                    "subtotal": "4.99",
                                                    "discount_total": "0.00",
                                                    "taxes": [
                                                        {
                                                            "tax_id": "1",
                                                            "name": "Sales Tax",
                                                            "amount": "0.44",
                                                            "included": false,
                                                            "rate": "8.875"
                                                        }
                                                    ],
                                                    "note": null
                                                }
                                            ],
                                            "currency": "USD",
                                            "subtotal": "4.99",
                                            "discount_total": "0.00",
                                            "service_charge": "0.00",
                                            "tax_total": "0.44",
                                            "taxes": [
                                                {
                                                    "tax_id": "1",
                                                    "name": "Sales Tax",
                                                    "amount": "0.44",
                                                    "included": false
                                                }
                                            ],
                                            "fees": [],
                                            "taxes_included_in_prices": false,
                                            "delivery_fee": "0.00",
                                            "tip": "1.00",
                                            "total": "5.43",
                                            "paid": true,
                                            "payments": [
                                                {
                                                    "id": "7688",
                                                    "payment_type_id": "2",
                                                    "amount": "5.43",
                                                    "tip_amount": "1.00",
                                                    "kind": "sale",
                                                    "reference": null,
                                                    "created_at": "2026-09-29T12:41:07-04:00"
                                                }
                                            ],
                                            "cancel_reason": null,
                                            "created_at": "2026-09-29T12:30:15-04:00",
                                            "updated_at": "2026-09-29T12:41:07-04:00",
                                            "closed_at": "2026-09-29T12:41:07-04:00"
                                        },
                                        {
                                            "id": "10432",
                                            "number": "42",
                                            "location_id": "3",
                                            "deleted": false,
                                            "source": {
                                                "app_client_id": "ppc_0123456789abcdef0123456789abcdef",
                                                "name": "Example Orders App",
                                                "external_id": "ord-8812"
                                            },
                                            "status": "new",
                                            "fulfillment": {
                                                "type": "pickup",
                                                "asap": false,
                                                "ready_at": "2026-09-29T18:30:00-04:00"
                                            },
                                            "customer": {
                                                "id": null,
                                                "name": null,
                                                "phone": "+13055550100"
                                            },
                                            "delivery_address": null,
                                            "note": "Ring the bell",
                                            "lines": [
                                                {
                                                    "id": "90001",
                                                    "item_id": "501",
                                                    "name": "Cheeseburger",
                                                    "quantity": "2",
                                                    "unit_price": "12.50",
                                                    "modifiers": [
                                                        {
                                                            "id": "90002",
                                                            "modifier_id": "901",
                                                            "name": "Extra cheese",
                                                            "quantity": "2",
                                                            "unit_price": "1.25",
                                                            "total": "2.50"
                                                        }
                                                    ],
                                                    "modifiers_total": "2.50",
                                                    "subtotal": "27.50",
                                                    "discount_total": "0.00",
                                                    "taxes": [
                                                        {
                                                            "tax_id": "1",
                                                            "name": "Sales Tax",
                                                            "amount": "2.44",
                                                            "included": false,
                                                            "rate": "8.875"
                                                        }
                                                    ],
                                                    "note": "No onions"
                                                }
                                            ],
                                            "currency": "USD",
                                            "subtotal": "27.50",
                                            "discount_total": "0.00",
                                            "service_charge": "0.00",
                                            "tax_total": "2.44",
                                            "taxes": [
                                                {
                                                    "tax_id": "1",
                                                    "name": "Sales Tax",
                                                    "amount": "2.44",
                                                    "included": false
                                                }
                                            ],
                                            "fees": [],
                                            "taxes_included_in_prices": false,
                                            "delivery_fee": "0.00",
                                            "tip": "3.00",
                                            "total": "29.94",
                                            "paid": false,
                                            "payments": [],
                                            "cancel_reason": null,
                                            "created_at": "2026-09-29T17:52:10-04:00",
                                            "updated_at": "2026-09-29T17:52:10-04:00",
                                            "closed_at": null
                                        }
                                    ],
                                    "next_cursor": null,
                                    "sync_token": "eyJ2IjoxLCJ0IjoicyIsInIiOiJpdGVtcyIsInciOjE3OTAwMDAwMDB9.Qm9ndXNTaWduYXR1cmU"
                                }
                            }
                        },
                        "headers": {
                            "X-Request-Id": {
                                "$ref": "#/components/headers/X-Request-Id"
                            },
                            "PalomaPOS-Api-Version": {
                                "$ref": "#/components/headers/PalomaPOS-Api-Version"
                            }
                        }
                    },
                    "400": {
                        "description": "invalid_request (limit, cursor, since, location_id, created_after)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                },
                                "example": {
                                    "error": {
                                        "code": "invalid_request",
                                        "message": "limit must be an integer between 1 and 200.",
                                        "retryable": false,
                                        "request_id": "req_4f1c2a9be07d5e8a1b3c6d20",
                                        "details": {
                                            "fields": {
                                                "limit": "out_of_range"
                                            }
                                        }
                                    }
                                }
                            }
                        },
                        "headers": {
                            "X-Request-Id": {
                                "$ref": "#/components/headers/X-Request-Id"
                            },
                            "PalomaPOS-Api-Version": {
                                "$ref": "#/components/headers/PalomaPOS-Api-Version"
                            }
                        }
                    },
                    "401": {
                        "description": "invalid_token",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                },
                                "example": {
                                    "error": {
                                        "code": "invalid_token",
                                        "message": "The access token is missing, expired or revoked.",
                                        "retryable": false,
                                        "request_id": "req_4f1c2a9be07d5e8a1b3c6d20",
                                        "details": {}
                                    }
                                }
                            }
                        },
                        "headers": {
                            "X-Request-Id": {
                                "$ref": "#/components/headers/X-Request-Id"
                            },
                            "PalomaPOS-Api-Version": {
                                "$ref": "#/components/headers/PalomaPOS-Api-Version"
                            }
                        }
                    },
                    "403": {
                        "description": "insufficient_scope / not_owner",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                },
                                "example": {
                                    "error": {
                                        "code": "insufficient_scope",
                                        "message": "The access token does not grant the scope required by this operation.",
                                        "retryable": false,
                                        "request_id": "req_4f1c2a9be07d5e8a1b3c6d20",
                                        "details": {
                                            "required_scope": "orders:read"
                                        }
                                    }
                                }
                            }
                        },
                        "headers": {
                            "X-Request-Id": {
                                "$ref": "#/components/headers/X-Request-Id"
                            },
                            "PalomaPOS-Api-Version": {
                                "$ref": "#/components/headers/PalomaPOS-Api-Version"
                            }
                        }
                    },
                    "410": {
                        "description": "sync_token_expired — do a full pass",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                },
                                "example": {
                                    "error": {
                                        "code": "sync_token_expired",
                                        "message": "The sync_token is older than 20 days; deletions since then are no longer known. Do a full pass without since.",
                                        "retryable": false,
                                        "request_id": "req_4f1c2a9be07d5e8a1b3c6d20",
                                        "details": {
                                            "max_age_days": 20
                                        }
                                    }
                                }
                            }
                        },
                        "headers": {
                            "X-Request-Id": {
                                "$ref": "#/components/headers/X-Request-Id"
                            },
                            "PalomaPOS-Api-Version": {
                                "$ref": "#/components/headers/PalomaPOS-Api-Version"
                            }
                        }
                    },
                    "429": {
                        "description": "rate_limited",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                },
                                "example": {
                                    "error": {
                                        "code": "rate_limited",
                                        "message": "Rate limit exceeded: 600 read requests per minute for this app and account.",
                                        "retryable": true,
                                        "request_id": "req_4f1c2a9be07d5e8a1b3c6d20",
                                        "details": {
                                            "limit": 600,
                                            "kind": "read",
                                            "retry_after": 17
                                        }
                                    }
                                }
                            }
                        },
                        "headers": {
                            "Retry-After": {
                                "$ref": "#/components/headers/Retry-After"
                            },
                            "X-Request-Id": {
                                "$ref": "#/components/headers/X-Request-Id"
                            },
                            "PalomaPOS-Api-Version": {
                                "$ref": "#/components/headers/PalomaPOS-Api-Version"
                            }
                        }
                    },
                    "500": {
                        "$ref": "#/components/responses/InternalError"
                    },
                    "503": {
                        "$ref": "#/components/responses/Unavailable"
                    }
                },
                "parameters": [
                    {
                        "name": "limit",
                        "in": "query",
                        "schema": {
                            "type": "integer",
                            "minimum": 1,
                            "maximum": 200,
                            "default": 100
                        }
                    },
                    {
                        "name": "cursor",
                        "in": "query",
                        "schema": {
                            "type": "string"
                        }
                    },
                    {
                        "name": "since",
                        "in": "query",
                        "description": "sync_token from a previous full pass; returns changes and deletions only.",
                        "schema": {
                            "type": "string"
                        }
                    },
                    {
                        "name": "location_id",
                        "in": "query",
                        "schema": {
                            "type": "string"
                        },
                        "description": "Only orders of this location. Part of the list, like created_after: a cursor or sync_token is accepted only with the same filters."
                    },
                    {
                        "name": "created_after",
                        "in": "query",
                        "description": "RFC 3339 with offset. Orders created at or after this moment — compared with each order's creation time in its location's time zone; on the first page of a full pass at most 400 days back (400 invalid_request `too_old`; later pages of the same pass are not re-checked). Default on a full pass: 400 days back. Part of the list: a cursor or sync_token is accepted only with the same location_id and created_after it was issued for (otherwise 400 invalid_request).",
                        "schema": {
                            "type": "string",
                            "format": "date-time"
                        }
                    }
                ],
                "operationId": "getOrders",
                "description": "All orders of the account, any source. The first pass returns every order once, in the order of its last header change; it covers orders created at most 400 days ago (created_after defaults to — and on the first page may not be earlier than — 400 days back); older orders are available by id. Pass the last page's sync_token as `since` to receive what changed afterwards: new orders, header edits, status changes made on the POS (the delivery row), payments and refunds, discounts and taxes — also when only those rows changed (a POS on API v1.9 does not touch the order header then) — and deletions (`deleted: true`). Every changed order comes once per since pass, at its first change in the window; one changed again while you page may come twice — upsert by id. Not covered: an edit of order lines alone (t_order has no change time) is seen only together with a header, delivery, payment, discount or tax change, and an edit of the customer card (s_clients) is not a change of the order. Statuses are polled this way (every 15–30 s while the app has open orders). Needs the keys of tenant migration 20260929_platform_list_indexes on large accounts. A page may hold fewer than `limit` orders while `next_cursor` is set: keep paging until it is null."
            }
        },
        "/orders/{id}": {
            "get": {
                "summary": "One order",
                "tags": [
                    "Orders"
                ],
                "security": [
                    {
                        "oauth2": [
                            "orders:read"
                        ]
                    },
                    {
                        "personalKey": []
                    }
                ],
                "x-palomapos-phase": "1b",
                "responses": {
                    "200": {
                        "description": "OK",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Order"
                                },
                                "example": {
                                    "id": "10432",
                                    "number": "42",
                                    "location_id": "3",
                                    "deleted": false,
                                    "source": {
                                        "app_client_id": "ppc_0123456789abcdef0123456789abcdef",
                                        "name": "Example Orders App",
                                        "external_id": "ord-8812"
                                    },
                                    "status": "new",
                                    "fulfillment": {
                                        "type": "pickup",
                                        "asap": false,
                                        "ready_at": "2026-09-29T18:30:00-04:00"
                                    },
                                    "customer": {
                                        "id": null,
                                        "name": null,
                                        "phone": "+13055550100"
                                    },
                                    "delivery_address": null,
                                    "note": "Ring the bell",
                                    "lines": [
                                        {
                                            "id": "90001",
                                            "item_id": "501",
                                            "name": "Cheeseburger",
                                            "quantity": "2",
                                            "unit_price": "12.50",
                                            "modifiers": [
                                                {
                                                    "id": "90002",
                                                    "modifier_id": "901",
                                                    "name": "Extra cheese",
                                                    "quantity": "2",
                                                    "unit_price": "1.25",
                                                    "total": "2.50"
                                                }
                                            ],
                                            "modifiers_total": "2.50",
                                            "subtotal": "27.50",
                                            "discount_total": "0.00",
                                            "taxes": [
                                                {
                                                    "tax_id": "1",
                                                    "name": "Sales Tax",
                                                    "amount": "2.44",
                                                    "included": false,
                                                    "rate": "8.875"
                                                }
                                            ],
                                            "note": "No onions"
                                        }
                                    ],
                                    "currency": "USD",
                                    "subtotal": "27.50",
                                    "discount_total": "0.00",
                                    "service_charge": "0.00",
                                    "tax_total": "2.44",
                                    "taxes": [
                                        {
                                            "tax_id": "1",
                                            "name": "Sales Tax",
                                            "amount": "2.44",
                                            "included": false
                                        }
                                    ],
                                    "fees": [],
                                    "taxes_included_in_prices": false,
                                    "delivery_fee": "0.00",
                                    "tip": "3.00",
                                    "total": "29.94",
                                    "paid": false,
                                    "payments": [],
                                    "cancel_reason": null,
                                    "created_at": "2026-09-29T17:52:10-04:00",
                                    "updated_at": "2026-09-29T17:52:10-04:00",
                                    "closed_at": null
                                }
                            }
                        },
                        "headers": {
                            "X-Request-Id": {
                                "$ref": "#/components/headers/X-Request-Id"
                            },
                            "PalomaPOS-Api-Version": {
                                "$ref": "#/components/headers/PalomaPOS-Api-Version"
                            }
                        }
                    },
                    "401": {
                        "description": "invalid_token",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                },
                                "example": {
                                    "error": {
                                        "code": "invalid_token",
                                        "message": "The access token is missing, expired or revoked.",
                                        "retryable": false,
                                        "request_id": "req_4f1c2a9be07d5e8a1b3c6d20",
                                        "details": {}
                                    }
                                }
                            }
                        },
                        "headers": {
                            "X-Request-Id": {
                                "$ref": "#/components/headers/X-Request-Id"
                            },
                            "PalomaPOS-Api-Version": {
                                "$ref": "#/components/headers/PalomaPOS-Api-Version"
                            }
                        }
                    },
                    "403": {
                        "description": "insufficient_scope / not_owner",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                },
                                "example": {
                                    "error": {
                                        "code": "insufficient_scope",
                                        "message": "The access token does not grant the scope required by this operation.",
                                        "retryable": false,
                                        "request_id": "req_4f1c2a9be07d5e8a1b3c6d20",
                                        "details": {
                                            "required_scope": "orders:read"
                                        }
                                    }
                                }
                            }
                        },
                        "headers": {
                            "X-Request-Id": {
                                "$ref": "#/components/headers/X-Request-Id"
                            },
                            "PalomaPOS-Api-Version": {
                                "$ref": "#/components/headers/PalomaPOS-Api-Version"
                            }
                        }
                    },
                    "404": {
                        "description": "not_found",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                },
                                "example": {
                                    "error": {
                                        "code": "not_found",
                                        "message": "The requested object does not exist in this account.",
                                        "retryable": false,
                                        "request_id": "req_4f1c2a9be07d5e8a1b3c6d20",
                                        "details": {}
                                    }
                                }
                            }
                        },
                        "headers": {
                            "X-Request-Id": {
                                "$ref": "#/components/headers/X-Request-Id"
                            },
                            "PalomaPOS-Api-Version": {
                                "$ref": "#/components/headers/PalomaPOS-Api-Version"
                            }
                        }
                    },
                    "429": {
                        "description": "rate_limited",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                },
                                "example": {
                                    "error": {
                                        "code": "rate_limited",
                                        "message": "Rate limit exceeded: 600 read requests per minute for this app and account.",
                                        "retryable": true,
                                        "request_id": "req_4f1c2a9be07d5e8a1b3c6d20",
                                        "details": {
                                            "limit": 600,
                                            "kind": "read",
                                            "retry_after": 17
                                        }
                                    }
                                }
                            }
                        },
                        "headers": {
                            "Retry-After": {
                                "$ref": "#/components/headers/Retry-After"
                            },
                            "X-Request-Id": {
                                "$ref": "#/components/headers/X-Request-Id"
                            },
                            "PalomaPOS-Api-Version": {
                                "$ref": "#/components/headers/PalomaPOS-Api-Version"
                            }
                        }
                    },
                    "500": {
                        "$ref": "#/components/responses/InternalError"
                    },
                    "503": {
                        "$ref": "#/components/responses/Unavailable"
                    }
                },
                "parameters": [
                    {
                        "name": "id",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "string"
                        }
                    }
                ],
                "operationId": "getOrdersById",
                "description": "One order of the account (any source). Deleted orders are returned with `deleted: true`."
            }
        },
        "/orders/{id}/payments": {
            "post": {
                "summary": "Record a payment taken outside the POS",
                "tags": [
                    "Orders"
                ],
                "security": [
                    {
                        "oauth2": [
                            "payments:write"
                        ]
                    },
                    {
                        "personalKey": []
                    }
                ],
                "x-palomapos-phase": "3",
                "responses": {
                    "200": {
                        "description": "The order with the payment (paid: true)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Order"
                                },
                                "example": {
                                    "id": "10432",
                                    "number": "42",
                                    "location_id": "3",
                                    "deleted": false,
                                    "source": {
                                        "app_client_id": "ppc_0123456789abcdef0123456789abcdef",
                                        "name": "Example Orders App",
                                        "external_id": "ord-8812"
                                    },
                                    "status": "new",
                                    "fulfillment": {
                                        "type": "pickup",
                                        "asap": false,
                                        "ready_at": "2026-09-29T18:30:00-04:00"
                                    },
                                    "customer": {
                                        "id": null,
                                        "name": null,
                                        "phone": "+13055550100"
                                    },
                                    "delivery_address": null,
                                    "note": "Ring the bell",
                                    "lines": [
                                        {
                                            "id": "90001",
                                            "item_id": "501",
                                            "name": "Cheeseburger",
                                            "quantity": "2",
                                            "unit_price": "12.50",
                                            "modifiers": [
                                                {
                                                    "id": "90002",
                                                    "modifier_id": "901",
                                                    "name": "Extra cheese",
                                                    "quantity": "2",
                                                    "unit_price": "1.25",
                                                    "total": "2.50"
                                                }
                                            ],
                                            "modifiers_total": "2.50",
                                            "subtotal": "27.50",
                                            "discount_total": "0.00",
                                            "taxes": [
                                                {
                                                    "tax_id": "1",
                                                    "name": "Sales Tax",
                                                    "amount": "2.44",
                                                    "included": false,
                                                    "rate": "8.875"
                                                }
                                            ],
                                            "note": "No onions"
                                        }
                                    ],
                                    "currency": "USD",
                                    "subtotal": "27.50",
                                    "discount_total": "0.00",
                                    "service_charge": "0.00",
                                    "tax_total": "2.44",
                                    "taxes": [
                                        {
                                            "tax_id": "1",
                                            "name": "Sales Tax",
                                            "amount": "2.44",
                                            "included": false
                                        }
                                    ],
                                    "fees": [],
                                    "taxes_included_in_prices": false,
                                    "delivery_fee": "0.00",
                                    "tip": "3.00",
                                    "total": "29.94",
                                    "paid": true,
                                    "payments": [
                                        {
                                            "id": "7701",
                                            "payment_type_id": "31",
                                            "amount": "29.94",
                                            "tip_amount": "3.00",
                                            "kind": "sale",
                                            "reference": "pi_3Nx0example",
                                            "created_at": "2026-09-29T17:53:02-04:00"
                                        }
                                    ],
                                    "cancel_reason": null,
                                    "created_at": "2026-09-29T17:52:10-04:00",
                                    "updated_at": "2026-09-29T17:53:02-04:00",
                                    "closed_at": null
                                }
                            }
                        },
                        "headers": {
                            "X-Request-Id": {
                                "$ref": "#/components/headers/X-Request-Id"
                            },
                            "PalomaPOS-Api-Version": {
                                "$ref": "#/components/headers/PalomaPOS-Api-Version"
                            },
                            "Idempotent-Replayed": {
                                "$ref": "#/components/headers/Idempotent-Replayed"
                            }
                        }
                    },
                    "400": {
                        "description": "invalid_request — details.fields: amount, tip_amount (exceeds_amount), provider, reference",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                },
                                "example": {
                                    "error": {
                                        "code": "invalid_request",
                                        "message": "The request body is invalid: see details.fields.",
                                        "retryable": false,
                                        "request_id": "req_4f1c2a9be07d5e8a1b3c6d20",
                                        "details": {
                                            "fields": {
                                                "amount": "invalid"
                                            }
                                        }
                                    }
                                }
                            }
                        },
                        "headers": {
                            "X-Request-Id": {
                                "$ref": "#/components/headers/X-Request-Id"
                            },
                            "PalomaPOS-Api-Version": {
                                "$ref": "#/components/headers/PalomaPOS-Api-Version"
                            }
                        }
                    },
                    "401": {
                        "description": "invalid_token",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                },
                                "example": {
                                    "error": {
                                        "code": "invalid_token",
                                        "message": "The access token is missing, expired or revoked.",
                                        "retryable": false,
                                        "request_id": "req_4f1c2a9be07d5e8a1b3c6d20",
                                        "details": {}
                                    }
                                }
                            }
                        },
                        "headers": {
                            "X-Request-Id": {
                                "$ref": "#/components/headers/X-Request-Id"
                            },
                            "PalomaPOS-Api-Version": {
                                "$ref": "#/components/headers/PalomaPOS-Api-Version"
                            }
                        }
                    },
                    "403": {
                        "description": "insufficient_scope (payments:write) / not_owner",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                },
                                "examples": {
                                    "insufficient_scope": {
                                        "summary": "insufficient_scope",
                                        "value": {
                                            "error": {
                                                "code": "insufficient_scope",
                                                "message": "The access token does not grant the scope required by this operation.",
                                                "retryable": false,
                                                "request_id": "req_4f1c2a9be07d5e8a1b3c6d20",
                                                "details": {
                                                    "required_scope": "payments:write"
                                                }
                                            }
                                        }
                                    },
                                    "not_owner": {
                                        "summary": "not_owner",
                                        "value": {
                                            "error": {
                                                "code": "not_owner",
                                                "message": "Only orders created by this app can be changed by it.",
                                                "retryable": false,
                                                "request_id": "req_4f1c2a9be07d5e8a1b3c6d20",
                                                "details": {}
                                            }
                                        }
                                    }
                                }
                            }
                        },
                        "headers": {
                            "X-Request-Id": {
                                "$ref": "#/components/headers/X-Request-Id"
                            },
                            "PalomaPOS-Api-Version": {
                                "$ref": "#/components/headers/PalomaPOS-Api-Version"
                            }
                        }
                    },
                    "404": {
                        "description": "not_found (also when the orders flag is off)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                },
                                "example": {
                                    "error": {
                                        "code": "not_found",
                                        "message": "The requested object does not exist in this account.",
                                        "retryable": false,
                                        "request_id": "req_4f1c2a9be07d5e8a1b3c6d20",
                                        "details": {}
                                    }
                                }
                            }
                        },
                        "headers": {
                            "X-Request-Id": {
                                "$ref": "#/components/headers/X-Request-Id"
                            },
                            "PalomaPOS-Api-Version": {
                                "$ref": "#/components/headers/PalomaPOS-Api-Version"
                            }
                        }
                    },
                    "409": {
                        "description": "total_mismatch — details.expected (amount due), details.actual; invalid_state — details.reason: order_closed | order_cancelled | already_paid; idempotency_key_reused / idempotency_in_progress (retryable)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                },
                                "examples": {
                                    "total_mismatch": {
                                        "summary": "total_mismatch",
                                        "value": {
                                            "error": {
                                                "code": "total_mismatch",
                                                "message": "amount must equal the amount due for the order.",
                                                "retryable": false,
                                                "request_id": "req_4f1c2a9be07d5e8a1b3c6d20",
                                                "details": {
                                                    "expected": "29.94",
                                                    "actual": "26.94"
                                                }
                                            }
                                        }
                                    },
                                    "invalid_state": {
                                        "summary": "invalid_state — already_paid",
                                        "value": {
                                            "error": {
                                                "code": "invalid_state",
                                                "message": "The order is already paid.",
                                                "retryable": false,
                                                "request_id": "req_4f1c2a9be07d5e8a1b3c6d20",
                                                "details": {
                                                    "reason": "already_paid",
                                                    "status": "new"
                                                }
                                            }
                                        }
                                    },
                                    "idempotency_key_reused": {
                                        "summary": "idempotency_key_reused",
                                        "value": {
                                            "error": {
                                                "code": "idempotency_key_reused",
                                                "message": "This Idempotency-Key was already used with a different request. Use a new key for a new request.",
                                                "retryable": false,
                                                "request_id": "req_4f1c2a9be07d5e8a1b3c6d20",
                                                "details": {}
                                            }
                                        }
                                    },
                                    "idempotency_in_progress": {
                                        "summary": "idempotency_in_progress",
                                        "value": {
                                            "error": {
                                                "code": "idempotency_in_progress",
                                                "message": "A request with this Idempotency-Key is still being processed. Retry with the same key shortly.",
                                                "retryable": true,
                                                "request_id": "req_4f1c2a9be07d5e8a1b3c6d20",
                                                "details": {}
                                            }
                                        }
                                    }
                                }
                            }
                        },
                        "headers": {
                            "X-Request-Id": {
                                "$ref": "#/components/headers/X-Request-Id"
                            },
                            "PalomaPOS-Api-Version": {
                                "$ref": "#/components/headers/PalomaPOS-Api-Version"
                            },
                            "Retry-After": {
                                "$ref": "#/components/headers/Retry-After",
                                "description": "Only with `idempotency_in_progress`."
                            }
                        }
                    },
                    "429": {
                        "description": "rate_limited",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                },
                                "example": {
                                    "error": {
                                        "code": "rate_limited",
                                        "message": "Rate limit exceeded: 60 write requests per minute for this app and account.",
                                        "retryable": true,
                                        "request_id": "req_4f1c2a9be07d5e8a1b3c6d20",
                                        "details": {
                                            "limit": 60,
                                            "kind": "write",
                                            "retry_after": 23
                                        }
                                    }
                                }
                            }
                        },
                        "headers": {
                            "Retry-After": {
                                "$ref": "#/components/headers/Retry-After"
                            },
                            "X-Request-Id": {
                                "$ref": "#/components/headers/X-Request-Id"
                            },
                            "PalomaPOS-Api-Version": {
                                "$ref": "#/components/headers/PalomaPOS-Api-Version"
                            }
                        }
                    },
                    "500": {
                        "$ref": "#/components/responses/InternalError"
                    },
                    "503": {
                        "description": "temporarily_unavailable — the order is being changed by another request; retry with the same key · or `account_not_ready` (not retryable): this business account's database has not been upgraded for the API yet",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                },
                                "example": {
                                    "error": {
                                        "code": "temporarily_unavailable",
                                        "message": "The service is temporarily unavailable. Retry later.",
                                        "retryable": true,
                                        "request_id": "req_4f1c2a9be07d5e8a1b3c6d20",
                                        "details": {}
                                    }
                                }
                            }
                        },
                        "headers": {
                            "Retry-After": {
                                "$ref": "#/components/headers/Retry-After"
                            },
                            "X-Request-Id": {
                                "$ref": "#/components/headers/X-Request-Id"
                            },
                            "PalomaPOS-Api-Version": {
                                "$ref": "#/components/headers/PalomaPOS-Api-Version"
                            }
                        }
                    }
                },
                "description": "Records a payment taken outside the POS (the app's provider) for an order created by the calling app (always priced by the server), open and not cancelled. Written like a bank order: a sale row in the order's payments with the app's own payment type (created once, named after the app), the provider reference and the tip; the delivery row is marked paid. The order stays open — the POS closes and posts it into the shift. Recording the same reference again returns the order unchanged.",
                "parameters": [
                    {
                        "name": "id",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "string"
                        }
                    },
                    {
                        "name": "Idempotency-Key",
                        "in": "header",
                        "required": true,
                        "schema": {
                            "type": "string",
                            "maxLength": 64
                        },
                        "description": "Required. 1–64 printable ASCII characters, case-sensitive, scoped to the app and account, kept 24 h. The same key with the same request (method, path, query, JSON body regardless of key order and whitespace) returns the stored response with header `Idempotent-Replayed: true`; with a different request — 409 idempotency_key_reused. While the first request with this key is still running — 409 idempotency_in_progress (retryable, Retry-After: 1). Responses to 400, 429 and 5xx are not stored: retrying with the same key runs the operation again."
                    }
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/PaymentInput"
                            },
                            "example": {
                                "amount": "29.94",
                                "tip_amount": "3.00",
                                "provider": "stripe",
                                "reference": "pi_3Nx0example"
                            }
                        }
                    }
                },
                "operationId": "postOrdersPayments"
            }
        },
        "/orders/{id}/cancel": {
            "post": {
                "summary": "Cancel an order created by this app",
                "tags": [
                    "Orders"
                ],
                "security": [
                    {
                        "oauth2": [
                            "orders:write"
                        ]
                    },
                    {
                        "personalKey": []
                    }
                ],
                "x-palomapos-phase": "2",
                "responses": {
                    "200": {
                        "description": "The order with status cancelled",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Order"
                                },
                                "example": {
                                    "id": "10432",
                                    "number": "42",
                                    "location_id": "3",
                                    "deleted": false,
                                    "source": {
                                        "app_client_id": "ppc_0123456789abcdef0123456789abcdef",
                                        "name": "Example Orders App",
                                        "external_id": "ord-8812"
                                    },
                                    "status": "cancelled",
                                    "fulfillment": {
                                        "type": "pickup",
                                        "asap": false,
                                        "ready_at": "2026-09-29T18:30:00-04:00"
                                    },
                                    "customer": {
                                        "id": null,
                                        "name": null,
                                        "phone": "+13055550100"
                                    },
                                    "delivery_address": null,
                                    "note": "Ring the bell",
                                    "lines": [
                                        {
                                            "id": "90001",
                                            "item_id": "501",
                                            "name": "Cheeseburger",
                                            "quantity": "2",
                                            "unit_price": "12.50",
                                            "modifiers": [
                                                {
                                                    "id": "90002",
                                                    "modifier_id": "901",
                                                    "name": "Extra cheese",
                                                    "quantity": "2",
                                                    "unit_price": "1.25",
                                                    "total": "2.50"
                                                }
                                            ],
                                            "modifiers_total": "2.50",
                                            "subtotal": "27.50",
                                            "discount_total": "0.00",
                                            "taxes": [
                                                {
                                                    "tax_id": "1",
                                                    "name": "Sales Tax",
                                                    "amount": "2.44",
                                                    "included": false,
                                                    "rate": "8.875"
                                                }
                                            ],
                                            "note": "No onions"
                                        }
                                    ],
                                    "currency": "USD",
                                    "subtotal": "27.50",
                                    "discount_total": "0.00",
                                    "service_charge": "0.00",
                                    "tax_total": "2.44",
                                    "taxes": [
                                        {
                                            "tax_id": "1",
                                            "name": "Sales Tax",
                                            "amount": "2.44",
                                            "included": false
                                        }
                                    ],
                                    "fees": [],
                                    "taxes_included_in_prices": false,
                                    "delivery_fee": "0.00",
                                    "tip": "3.00",
                                    "total": "29.94",
                                    "paid": false,
                                    "payments": [],
                                    "cancel_reason": "Guest cancelled by phone",
                                    "created_at": "2026-09-29T17:52:10-04:00",
                                    "updated_at": "2026-09-29T17:58:40-04:00",
                                    "closed_at": null
                                }
                            }
                        },
                        "headers": {
                            "X-Request-Id": {
                                "$ref": "#/components/headers/X-Request-Id"
                            },
                            "PalomaPOS-Api-Version": {
                                "$ref": "#/components/headers/PalomaPOS-Api-Version"
                            },
                            "Idempotent-Replayed": {
                                "$ref": "#/components/headers/Idempotent-Replayed"
                            }
                        }
                    },
                    "400": {
                        "description": "invalid_request — reason required / too_long; Idempotency-Key required",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                },
                                "example": {
                                    "error": {
                                        "code": "invalid_request",
                                        "message": "The request body is invalid: see details.fields.",
                                        "retryable": false,
                                        "request_id": "req_4f1c2a9be07d5e8a1b3c6d20",
                                        "details": {
                                            "fields": {
                                                "reason": "required"
                                            }
                                        }
                                    }
                                }
                            }
                        },
                        "headers": {
                            "X-Request-Id": {
                                "$ref": "#/components/headers/X-Request-Id"
                            },
                            "PalomaPOS-Api-Version": {
                                "$ref": "#/components/headers/PalomaPOS-Api-Version"
                            }
                        }
                    },
                    "401": {
                        "description": "invalid_token",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                },
                                "example": {
                                    "error": {
                                        "code": "invalid_token",
                                        "message": "The access token is missing, expired or revoked.",
                                        "retryable": false,
                                        "request_id": "req_4f1c2a9be07d5e8a1b3c6d20",
                                        "details": {}
                                    }
                                }
                            }
                        },
                        "headers": {
                            "X-Request-Id": {
                                "$ref": "#/components/headers/X-Request-Id"
                            },
                            "PalomaPOS-Api-Version": {
                                "$ref": "#/components/headers/PalomaPOS-Api-Version"
                            }
                        }
                    },
                    "403": {
                        "description": "insufficient_scope (orders:write) / not_owner — the order was created on the POS or by another app",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                },
                                "examples": {
                                    "insufficient_scope": {
                                        "summary": "insufficient_scope",
                                        "value": {
                                            "error": {
                                                "code": "insufficient_scope",
                                                "message": "The access token does not grant the scope required by this operation.",
                                                "retryable": false,
                                                "request_id": "req_4f1c2a9be07d5e8a1b3c6d20",
                                                "details": {
                                                    "required_scope": "orders:write"
                                                }
                                            }
                                        }
                                    },
                                    "not_owner": {
                                        "summary": "not_owner",
                                        "value": {
                                            "error": {
                                                "code": "not_owner",
                                                "message": "Only orders created by this app can be changed by it.",
                                                "retryable": false,
                                                "request_id": "req_4f1c2a9be07d5e8a1b3c6d20",
                                                "details": {}
                                            }
                                        }
                                    }
                                }
                            }
                        },
                        "headers": {
                            "X-Request-Id": {
                                "$ref": "#/components/headers/X-Request-Id"
                            },
                            "PalomaPOS-Api-Version": {
                                "$ref": "#/components/headers/PalomaPOS-Api-Version"
                            }
                        }
                    },
                    "404": {
                        "description": "not_found (also when the orders flag is off)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                },
                                "example": {
                                    "error": {
                                        "code": "not_found",
                                        "message": "The requested object does not exist in this account.",
                                        "retryable": false,
                                        "request_id": "req_4f1c2a9be07d5e8a1b3c6d20",
                                        "details": {}
                                    }
                                }
                            }
                        },
                        "headers": {
                            "X-Request-Id": {
                                "$ref": "#/components/headers/X-Request-Id"
                            },
                            "PalomaPOS-Api-Version": {
                                "$ref": "#/components/headers/PalomaPOS-Api-Version"
                            }
                        }
                    },
                    "409": {
                        "description": "invalid_state — details.reason: status_not_cancellable | order_closed, details.status; idempotency_key_reused / idempotency_in_progress (retryable)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                },
                                "examples": {
                                    "invalid_state": {
                                        "summary": "invalid_state — status_not_cancellable",
                                        "value": {
                                            "error": {
                                                "code": "invalid_state",
                                                "message": "The order can no longer be cancelled by the app.",
                                                "retryable": false,
                                                "request_id": "req_4f1c2a9be07d5e8a1b3c6d20",
                                                "details": {
                                                    "reason": "status_not_cancellable",
                                                    "status": "in_progress"
                                                }
                                            }
                                        }
                                    },
                                    "idempotency_key_reused": {
                                        "summary": "idempotency_key_reused",
                                        "value": {
                                            "error": {
                                                "code": "idempotency_key_reused",
                                                "message": "This Idempotency-Key was already used with a different request. Use a new key for a new request.",
                                                "retryable": false,
                                                "request_id": "req_4f1c2a9be07d5e8a1b3c6d20",
                                                "details": {}
                                            }
                                        }
                                    },
                                    "idempotency_in_progress": {
                                        "summary": "idempotency_in_progress",
                                        "value": {
                                            "error": {
                                                "code": "idempotency_in_progress",
                                                "message": "A request with this Idempotency-Key is still being processed. Retry with the same key shortly.",
                                                "retryable": true,
                                                "request_id": "req_4f1c2a9be07d5e8a1b3c6d20",
                                                "details": {}
                                            }
                                        }
                                    }
                                }
                            }
                        },
                        "headers": {
                            "X-Request-Id": {
                                "$ref": "#/components/headers/X-Request-Id"
                            },
                            "PalomaPOS-Api-Version": {
                                "$ref": "#/components/headers/PalomaPOS-Api-Version"
                            },
                            "Retry-After": {
                                "$ref": "#/components/headers/Retry-After",
                                "description": "Only with `idempotency_in_progress`."
                            }
                        }
                    },
                    "429": {
                        "description": "rate_limited",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                },
                                "example": {
                                    "error": {
                                        "code": "rate_limited",
                                        "message": "Rate limit exceeded: 60 write requests per minute for this app and account.",
                                        "retryable": true,
                                        "request_id": "req_4f1c2a9be07d5e8a1b3c6d20",
                                        "details": {
                                            "limit": 60,
                                            "kind": "write",
                                            "retry_after": 23
                                        }
                                    }
                                }
                            }
                        },
                        "headers": {
                            "Retry-After": {
                                "$ref": "#/components/headers/Retry-After"
                            },
                            "X-Request-Id": {
                                "$ref": "#/components/headers/X-Request-Id"
                            },
                            "PalomaPOS-Api-Version": {
                                "$ref": "#/components/headers/PalomaPOS-Api-Version"
                            }
                        }
                    },
                    "500": {
                        "$ref": "#/components/responses/InternalError"
                    },
                    "503": {
                        "description": "temporarily_unavailable — the order is being changed by another request; retry with the same key · or `account_not_ready` (not retryable): this business account's database has not been upgraded for the API yet",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                },
                                "example": {
                                    "error": {
                                        "code": "temporarily_unavailable",
                                        "message": "The service is temporarily unavailable. Retry later.",
                                        "retryable": true,
                                        "request_id": "req_4f1c2a9be07d5e8a1b3c6d20",
                                        "details": {}
                                    }
                                }
                            }
                        },
                        "headers": {
                            "Retry-After": {
                                "$ref": "#/components/headers/Retry-After"
                            },
                            "X-Request-Id": {
                                "$ref": "#/components/headers/X-Request-Id"
                            },
                            "PalomaPOS-Api-Version": {
                                "$ref": "#/components/headers/PalomaPOS-Api-Version"
                            }
                        }
                    }
                },
                "description": "Cancels an order created by the calling app while its status is new or accepted and the check is open. Nothing is deleted: the delivery status becomes cancelled (6) with the reason, as when the cashier cancels; the POS is notified through the socket. For an order paid through POST /orders/{id}/payments a refund row is recorded (kind refund, operation_type 1, the same provider reference), the order is no longer marked paid (`paid: false`, no tip) and the payment journal records the refund, so the payment is not counted as revenue; the money itself is returned by the app's provider. Cancelling an already cancelled order returns it unchanged (200).",
                "parameters": [
                    {
                        "name": "id",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "string"
                        }
                    },
                    {
                        "name": "Idempotency-Key",
                        "in": "header",
                        "required": true,
                        "schema": {
                            "type": "string",
                            "maxLength": 64
                        },
                        "description": "Required. 1–64 printable ASCII characters, case-sensitive, scoped to the app and account, kept 24 h. The same key with the same request (method, path, query, JSON body regardless of key order and whitespace) returns the stored response with header `Idempotent-Replayed: true`; with a different request — 409 idempotency_key_reused. While the first request with this key is still running — 409 idempotency_in_progress (retryable, Retry-After: 1). Responses to 400, 429 and 5xx are not stored: retrying with the same key runs the operation again."
                    }
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/CancelInput"
                            },
                            "example": {
                                "reason": "Guest cancelled by phone"
                            }
                        }
                    }
                },
                "operationId": "postOrdersCancel"
            }
        },
        "/customers": {
            "get": {
                "summary": "Customers",
                "tags": [
                    "History"
                ],
                "security": [
                    {
                        "oauth2": [
                            "customers:read"
                        ]
                    },
                    {
                        "personalKey": []
                    }
                ],
                "x-palomapos-phase": "1b",
                "responses": {
                    "200": {
                        "description": "OK",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "type": "array",
                                            "items": {
                                                "$ref": "#/components/schemas/Customer"
                                            }
                                        },
                                        "next_cursor": {
                                            "type": [
                                                "string",
                                                "null"
                                            ]
                                        },
                                        "sync_token": {
                                            "type": [
                                                "string",
                                                "null"
                                            ],
                                            "description": "null on every page but the last; on the last page pass it as `since` to receive only what changed afterwards (deletions included)."
                                        }
                                    },
                                    "required": [
                                        "data",
                                        "next_cursor",
                                        "sync_token"
                                    ]
                                },
                                "example": {
                                    "data": [
                                        {
                                            "id": "77",
                                            "name": "Sam Guest",
                                            "phone": "+13055550100",
                                            "email": "sam.guest@example.com",
                                            "birthday": "1990-05-17",
                                            "deleted": false,
                                            "updated_at": "2026-09-29T09:05:00-04:00"
                                        },
                                        {
                                            "id": "81",
                                            "name": null,
                                            "phone": null,
                                            "email": null,
                                            "birthday": null,
                                            "deleted": true,
                                            "updated_at": "2026-09-29T09:06:10-04:00"
                                        }
                                    ],
                                    "next_cursor": null,
                                    "sync_token": "eyJ2IjoxLCJ0IjoicyIsInIiOiJpdGVtcyIsInciOjE3OTAwMDAwMDB9.Qm9ndXNTaWduYXR1cmU"
                                }
                            }
                        },
                        "headers": {
                            "X-Request-Id": {
                                "$ref": "#/components/headers/X-Request-Id"
                            },
                            "PalomaPOS-Api-Version": {
                                "$ref": "#/components/headers/PalomaPOS-Api-Version"
                            }
                        }
                    },
                    "400": {
                        "description": "invalid_request — limit, cursor or since is malformed (`details.fields`)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                },
                                "example": {
                                    "error": {
                                        "code": "invalid_request",
                                        "message": "limit must be an integer between 1 and 200.",
                                        "retryable": false,
                                        "request_id": "req_4f1c2a9be07d5e8a1b3c6d20",
                                        "details": {
                                            "fields": {
                                                "limit": "out_of_range"
                                            }
                                        }
                                    }
                                }
                            }
                        },
                        "headers": {
                            "X-Request-Id": {
                                "$ref": "#/components/headers/X-Request-Id"
                            },
                            "PalomaPOS-Api-Version": {
                                "$ref": "#/components/headers/PalomaPOS-Api-Version"
                            }
                        }
                    },
                    "401": {
                        "description": "invalid_token",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                },
                                "example": {
                                    "error": {
                                        "code": "invalid_token",
                                        "message": "The access token is missing, expired or revoked.",
                                        "retryable": false,
                                        "request_id": "req_4f1c2a9be07d5e8a1b3c6d20",
                                        "details": {}
                                    }
                                }
                            }
                        },
                        "headers": {
                            "X-Request-Id": {
                                "$ref": "#/components/headers/X-Request-Id"
                            },
                            "PalomaPOS-Api-Version": {
                                "$ref": "#/components/headers/PalomaPOS-Api-Version"
                            }
                        }
                    },
                    "403": {
                        "description": "insufficient_scope / not_owner",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                },
                                "example": {
                                    "error": {
                                        "code": "insufficient_scope",
                                        "message": "The access token does not grant the scope required by this operation.",
                                        "retryable": false,
                                        "request_id": "req_4f1c2a9be07d5e8a1b3c6d20",
                                        "details": {
                                            "required_scope": "customers:read"
                                        }
                                    }
                                }
                            }
                        },
                        "headers": {
                            "X-Request-Id": {
                                "$ref": "#/components/headers/X-Request-Id"
                            },
                            "PalomaPOS-Api-Version": {
                                "$ref": "#/components/headers/PalomaPOS-Api-Version"
                            }
                        }
                    },
                    "410": {
                        "description": "sync_token_expired — do a full pass",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                },
                                "example": {
                                    "error": {
                                        "code": "sync_token_expired",
                                        "message": "The sync_token is older than 20 days; deletions since then are no longer known. Do a full pass without since.",
                                        "retryable": false,
                                        "request_id": "req_4f1c2a9be07d5e8a1b3c6d20",
                                        "details": {
                                            "max_age_days": 20
                                        }
                                    }
                                }
                            }
                        },
                        "headers": {
                            "X-Request-Id": {
                                "$ref": "#/components/headers/X-Request-Id"
                            },
                            "PalomaPOS-Api-Version": {
                                "$ref": "#/components/headers/PalomaPOS-Api-Version"
                            }
                        }
                    },
                    "429": {
                        "description": "rate_limited",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                },
                                "example": {
                                    "error": {
                                        "code": "rate_limited",
                                        "message": "Rate limit exceeded: 600 read requests per minute for this app and account.",
                                        "retryable": true,
                                        "request_id": "req_4f1c2a9be07d5e8a1b3c6d20",
                                        "details": {
                                            "limit": 600,
                                            "kind": "read",
                                            "retry_after": 17
                                        }
                                    }
                                }
                            }
                        },
                        "headers": {
                            "Retry-After": {
                                "$ref": "#/components/headers/Retry-After"
                            },
                            "X-Request-Id": {
                                "$ref": "#/components/headers/X-Request-Id"
                            },
                            "PalomaPOS-Api-Version": {
                                "$ref": "#/components/headers/PalomaPOS-Api-Version"
                            }
                        }
                    },
                    "500": {
                        "$ref": "#/components/responses/InternalError"
                    },
                    "503": {
                        "$ref": "#/components/responses/Unavailable"
                    }
                },
                "parameters": [
                    {
                        "name": "limit",
                        "in": "query",
                        "schema": {
                            "type": "integer",
                            "minimum": 1,
                            "maximum": 200,
                            "default": 100
                        }
                    },
                    {
                        "name": "cursor",
                        "in": "query",
                        "schema": {
                            "type": "string"
                        }
                    },
                    {
                        "name": "since",
                        "in": "query",
                        "description": "sync_token from a previous full pass; returns changes and deletions only.",
                        "schema": {
                            "type": "string"
                        }
                    }
                ],
                "operationId": "getCustomers",
                "description": "The customer base. Full pass (no `since`): live customers. With `since`: every customer record that changed, plus deletions — soft-deleted customers, records that stopped being customers, and records deleted outright (known for 20 days, then `410 sync_token_expired`) — as tombstones `deleted: true` without personal data. The account balance and bonus points are not part of v1: a balance change does not touch the customer record, so `since` could not report it. A tombstone can name a record you never received (for example, a supplier that was edited): deleting an unknown id is a no-op."
            }
        },
        "/employees": {
            "get": {
                "summary": "Employees",
                "tags": [
                    "History"
                ],
                "security": [
                    {
                        "oauth2": [
                            "staff:read"
                        ]
                    },
                    {
                        "personalKey": []
                    }
                ],
                "x-palomapos-phase": "1b",
                "responses": {
                    "200": {
                        "description": "OK",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "type": "array",
                                            "items": {
                                                "$ref": "#/components/schemas/Employee"
                                            }
                                        },
                                        "next_cursor": {
                                            "type": [
                                                "string",
                                                "null"
                                            ]
                                        },
                                        "sync_token": {
                                            "type": [
                                                "string",
                                                "null"
                                            ],
                                            "description": "null on every page but the last; on the last page pass it as `since` to receive only what changed afterwards (deletions included)."
                                        }
                                    },
                                    "required": [
                                        "data",
                                        "next_cursor",
                                        "sync_token"
                                    ]
                                },
                                "example": {
                                    "data": [
                                        {
                                            "id": "12",
                                            "name": "Alex Example",
                                            "position": "Server",
                                            "location_ids": [
                                                "3"
                                            ],
                                            "active": true,
                                            "deleted": false,
                                            "updated_at": "2026-09-29T07:30:00-04:00"
                                        }
                                    ],
                                    "next_cursor": null,
                                    "sync_token": "eyJ2IjoxLCJ0IjoicyIsInIiOiJpdGVtcyIsInciOjE3OTAwMDAwMDB9.Qm9ndXNTaWduYXR1cmU"
                                }
                            }
                        },
                        "headers": {
                            "X-Request-Id": {
                                "$ref": "#/components/headers/X-Request-Id"
                            },
                            "PalomaPOS-Api-Version": {
                                "$ref": "#/components/headers/PalomaPOS-Api-Version"
                            }
                        }
                    },
                    "400": {
                        "description": "invalid_request — limit, cursor or since is malformed (`details.fields`)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                },
                                "example": {
                                    "error": {
                                        "code": "invalid_request",
                                        "message": "limit must be an integer between 1 and 200.",
                                        "retryable": false,
                                        "request_id": "req_4f1c2a9be07d5e8a1b3c6d20",
                                        "details": {
                                            "fields": {
                                                "limit": "out_of_range"
                                            }
                                        }
                                    }
                                }
                            }
                        },
                        "headers": {
                            "X-Request-Id": {
                                "$ref": "#/components/headers/X-Request-Id"
                            },
                            "PalomaPOS-Api-Version": {
                                "$ref": "#/components/headers/PalomaPOS-Api-Version"
                            }
                        }
                    },
                    "401": {
                        "description": "invalid_token",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                },
                                "example": {
                                    "error": {
                                        "code": "invalid_token",
                                        "message": "The access token is missing, expired or revoked.",
                                        "retryable": false,
                                        "request_id": "req_4f1c2a9be07d5e8a1b3c6d20",
                                        "details": {}
                                    }
                                }
                            }
                        },
                        "headers": {
                            "X-Request-Id": {
                                "$ref": "#/components/headers/X-Request-Id"
                            },
                            "PalomaPOS-Api-Version": {
                                "$ref": "#/components/headers/PalomaPOS-Api-Version"
                            }
                        }
                    },
                    "403": {
                        "description": "insufficient_scope / not_owner",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                },
                                "example": {
                                    "error": {
                                        "code": "insufficient_scope",
                                        "message": "The access token does not grant the scope required by this operation.",
                                        "retryable": false,
                                        "request_id": "req_4f1c2a9be07d5e8a1b3c6d20",
                                        "details": {
                                            "required_scope": "staff:read"
                                        }
                                    }
                                }
                            }
                        },
                        "headers": {
                            "X-Request-Id": {
                                "$ref": "#/components/headers/X-Request-Id"
                            },
                            "PalomaPOS-Api-Version": {
                                "$ref": "#/components/headers/PalomaPOS-Api-Version"
                            }
                        }
                    },
                    "410": {
                        "description": "sync_token_expired — do a full pass",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                },
                                "example": {
                                    "error": {
                                        "code": "sync_token_expired",
                                        "message": "The sync_token is older than 20 days; deletions since then are no longer known. Do a full pass without since.",
                                        "retryable": false,
                                        "request_id": "req_4f1c2a9be07d5e8a1b3c6d20",
                                        "details": {
                                            "max_age_days": 20
                                        }
                                    }
                                }
                            }
                        },
                        "headers": {
                            "X-Request-Id": {
                                "$ref": "#/components/headers/X-Request-Id"
                            },
                            "PalomaPOS-Api-Version": {
                                "$ref": "#/components/headers/PalomaPOS-Api-Version"
                            }
                        }
                    },
                    "429": {
                        "description": "rate_limited",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                },
                                "example": {
                                    "error": {
                                        "code": "rate_limited",
                                        "message": "Rate limit exceeded: 600 read requests per minute for this app and account.",
                                        "retryable": true,
                                        "request_id": "req_4f1c2a9be07d5e8a1b3c6d20",
                                        "details": {
                                            "limit": 600,
                                            "kind": "read",
                                            "retry_after": 17
                                        }
                                    }
                                }
                            }
                        },
                        "headers": {
                            "Retry-After": {
                                "$ref": "#/components/headers/Retry-After"
                            },
                            "X-Request-Id": {
                                "$ref": "#/components/headers/X-Request-Id"
                            },
                            "PalomaPOS-Api-Version": {
                                "$ref": "#/components/headers/PalomaPOS-Api-Version"
                            }
                        }
                    },
                    "500": {
                        "$ref": "#/components/responses/InternalError"
                    },
                    "503": {
                        "$ref": "#/components/responses/Unavailable"
                    }
                },
                "parameters": [
                    {
                        "name": "limit",
                        "in": "query",
                        "schema": {
                            "type": "integer",
                            "minimum": 1,
                            "maximum": 200,
                            "default": 100
                        }
                    },
                    {
                        "name": "cursor",
                        "in": "query",
                        "schema": {
                            "type": "string"
                        }
                    },
                    {
                        "name": "since",
                        "in": "query",
                        "description": "sync_token from a previous full pass; returns changes and deletions only.",
                        "schema": {
                            "type": "string"
                        }
                    }
                ],
                "operationId": "getEmployees",
                "description": "Employees. Full pass: current employees (folders of the staff tree excluded). With `since`: employees whose card or workplaces changed, and deletions as tombstones `deleted: true`. A tombstone can name a record you never received (for example, an edited folder of the staff tree): deleting an unknown id is a no-op. Removing an employee from ALL workplaces and renaming a job position are not seen by `since` (nothing in the employee's records changes) — repeat a full pass periodically."
            }
        },
        "/shifts": {
            "get": {
                "summary": "Shifts",
                "tags": [
                    "History"
                ],
                "security": [
                    {
                        "oauth2": [
                            "staff:read"
                        ]
                    },
                    {
                        "personalKey": []
                    }
                ],
                "x-palomapos-phase": "1b",
                "responses": {
                    "200": {
                        "description": "OK",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "type": "array",
                                            "items": {
                                                "$ref": "#/components/schemas/Shift"
                                            }
                                        },
                                        "next_cursor": {
                                            "type": [
                                                "string",
                                                "null"
                                            ]
                                        },
                                        "sync_token": {
                                            "type": [
                                                "string",
                                                "null"
                                            ],
                                            "description": "null on every page but the last; on the last page pass it as `since` to receive only what changed afterwards (deletions included)."
                                        }
                                    },
                                    "required": [
                                        "data",
                                        "next_cursor",
                                        "sync_token"
                                    ]
                                },
                                "example": {
                                    "data": [
                                        {
                                            "id": "640",
                                            "location_id": "3",
                                            "opened_at": "2026-09-29T08:58:00-04:00",
                                            "closed_at": null,
                                            "closed": false,
                                            "opened_by_employee_id": "12",
                                            "updated_at": "2026-09-29T08:58:00-04:00"
                                        }
                                    ],
                                    "next_cursor": null,
                                    "sync_token": "eyJ2IjoxLCJ0IjoicyIsInIiOiJpdGVtcyIsInciOjE3OTAwMDAwMDB9.Qm9ndXNTaWduYXR1cmU"
                                }
                            }
                        },
                        "headers": {
                            "X-Request-Id": {
                                "$ref": "#/components/headers/X-Request-Id"
                            },
                            "PalomaPOS-Api-Version": {
                                "$ref": "#/components/headers/PalomaPOS-Api-Version"
                            }
                        }
                    },
                    "400": {
                        "description": "invalid_request — limit, cursor, since or location_id is malformed (`details.fields`)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                },
                                "example": {
                                    "error": {
                                        "code": "invalid_request",
                                        "message": "limit must be an integer between 1 and 200.",
                                        "retryable": false,
                                        "request_id": "req_4f1c2a9be07d5e8a1b3c6d20",
                                        "details": {
                                            "fields": {
                                                "limit": "out_of_range"
                                            }
                                        }
                                    }
                                }
                            }
                        },
                        "headers": {
                            "X-Request-Id": {
                                "$ref": "#/components/headers/X-Request-Id"
                            },
                            "PalomaPOS-Api-Version": {
                                "$ref": "#/components/headers/PalomaPOS-Api-Version"
                            }
                        }
                    },
                    "401": {
                        "description": "invalid_token",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                },
                                "example": {
                                    "error": {
                                        "code": "invalid_token",
                                        "message": "The access token is missing, expired or revoked.",
                                        "retryable": false,
                                        "request_id": "req_4f1c2a9be07d5e8a1b3c6d20",
                                        "details": {}
                                    }
                                }
                            }
                        },
                        "headers": {
                            "X-Request-Id": {
                                "$ref": "#/components/headers/X-Request-Id"
                            },
                            "PalomaPOS-Api-Version": {
                                "$ref": "#/components/headers/PalomaPOS-Api-Version"
                            }
                        }
                    },
                    "403": {
                        "description": "insufficient_scope / not_owner",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                },
                                "example": {
                                    "error": {
                                        "code": "insufficient_scope",
                                        "message": "The access token does not grant the scope required by this operation.",
                                        "retryable": false,
                                        "request_id": "req_4f1c2a9be07d5e8a1b3c6d20",
                                        "details": {
                                            "required_scope": "staff:read"
                                        }
                                    }
                                }
                            }
                        },
                        "headers": {
                            "X-Request-Id": {
                                "$ref": "#/components/headers/X-Request-Id"
                            },
                            "PalomaPOS-Api-Version": {
                                "$ref": "#/components/headers/PalomaPOS-Api-Version"
                            }
                        }
                    },
                    "410": {
                        "description": "sync_token_expired — do a full pass",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                },
                                "example": {
                                    "error": {
                                        "code": "sync_token_expired",
                                        "message": "The sync_token is older than 20 days; deletions since then are no longer known. Do a full pass without since.",
                                        "retryable": false,
                                        "request_id": "req_4f1c2a9be07d5e8a1b3c6d20",
                                        "details": {
                                            "max_age_days": 20
                                        }
                                    }
                                }
                            }
                        },
                        "headers": {
                            "X-Request-Id": {
                                "$ref": "#/components/headers/X-Request-Id"
                            },
                            "PalomaPOS-Api-Version": {
                                "$ref": "#/components/headers/PalomaPOS-Api-Version"
                            }
                        }
                    },
                    "429": {
                        "description": "rate_limited",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                },
                                "example": {
                                    "error": {
                                        "code": "rate_limited",
                                        "message": "Rate limit exceeded: 600 read requests per minute for this app and account.",
                                        "retryable": true,
                                        "request_id": "req_4f1c2a9be07d5e8a1b3c6d20",
                                        "details": {
                                            "limit": 600,
                                            "kind": "read",
                                            "retry_after": 17
                                        }
                                    }
                                }
                            }
                        },
                        "headers": {
                            "Retry-After": {
                                "$ref": "#/components/headers/Retry-After"
                            },
                            "X-Request-Id": {
                                "$ref": "#/components/headers/X-Request-Id"
                            },
                            "PalomaPOS-Api-Version": {
                                "$ref": "#/components/headers/PalomaPOS-Api-Version"
                            }
                        }
                    },
                    "500": {
                        "$ref": "#/components/responses/InternalError"
                    },
                    "503": {
                        "$ref": "#/components/responses/Unavailable"
                    }
                },
                "parameters": [
                    {
                        "name": "limit",
                        "in": "query",
                        "schema": {
                            "type": "integer",
                            "minimum": 1,
                            "maximum": 200,
                            "default": 100
                        }
                    },
                    {
                        "name": "cursor",
                        "in": "query",
                        "schema": {
                            "type": "string"
                        }
                    },
                    {
                        "name": "since",
                        "in": "query",
                        "description": "sync_token from a previous full pass; returns changes and deletions only.",
                        "schema": {
                            "type": "string"
                        }
                    },
                    {
                        "name": "location_id",
                        "in": "query",
                        "schema": {
                            "type": "string"
                        },
                        "description": "Only shifts of this location."
                    }
                ],
                "operationId": "getShifts",
                "description": "POS shifts, optionally of one location. With `location_id` the `next_cursor` and `sync_token` belong to that filtered list: pass them only with the same `location_id`. Shifts have no soft delete; a shift removed in the back office disappears from the next full pass and is not reported by `since`."
            }
        },
        "/reports/sales-daily": {
            "get": {
                "summary": "Sales per day and per item",
                "tags": [
                    "History"
                ],
                "security": [
                    {
                        "oauth2": [
                            "reports:read"
                        ]
                    },
                    {
                        "personalKey": []
                    }
                ],
                "x-palomapos-phase": "1b",
                "responses": {
                    "200": {
                        "description": "OK",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "currency": {
                                            "type": "string"
                                        },
                                        "data": {
                                            "type": "array",
                                            "items": {
                                                "$ref": "#/components/schemas/SalesDay"
                                            }
                                        }
                                    },
                                    "required": [
                                        "currency",
                                        "data"
                                    ]
                                },
                                "example": {
                                    "currency": "USD",
                                    "data": [
                                        {
                                            "date": "2026-09-28",
                                            "location_id": "3",
                                            "orders": 57,
                                            "gross": "1480.25",
                                            "discounts": "32.00",
                                            "service_charges": "0.00",
                                            "net": "1448.25",
                                            "tax": "128.53",
                                            "tax_included": "0.00",
                                            "items": [
                                                {
                                                    "item_id": "501",
                                                    "name": "Cheeseburger",
                                                    "quantity": "64",
                                                    "gross": "800.00"
                                                },
                                                {
                                                    "item_id": "502",
                                                    "name": "Fries",
                                                    "quantity": "71.5",
                                                    "gross": "356.79"
                                                }
                                            ]
                                        }
                                    ]
                                }
                            }
                        },
                        "headers": {
                            "X-Request-Id": {
                                "$ref": "#/components/headers/X-Request-Id"
                            },
                            "PalomaPOS-Api-Version": {
                                "$ref": "#/components/headers/PalomaPOS-Api-Version"
                            }
                        }
                    },
                    "400": {
                        "description": "invalid_request — `from`/`to` missing or not a date, `to` before `from`, or the period is longer than 92 days (`details.fields`, `details.max_days`)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                },
                                "example": {
                                    "error": {
                                        "code": "invalid_request",
                                        "message": "The period is 120 days; at most 92 days per request.",
                                        "retryable": false,
                                        "request_id": "req_4f1c2a9be07d5e8a1b3c6d20",
                                        "details": {
                                            "fields": {
                                                "to": "range_too_long"
                                            },
                                            "max_days": 92
                                        }
                                    }
                                }
                            }
                        },
                        "headers": {
                            "X-Request-Id": {
                                "$ref": "#/components/headers/X-Request-Id"
                            },
                            "PalomaPOS-Api-Version": {
                                "$ref": "#/components/headers/PalomaPOS-Api-Version"
                            }
                        }
                    },
                    "401": {
                        "description": "invalid_token",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                },
                                "example": {
                                    "error": {
                                        "code": "invalid_token",
                                        "message": "The access token is missing, expired or revoked.",
                                        "retryable": false,
                                        "request_id": "req_4f1c2a9be07d5e8a1b3c6d20",
                                        "details": {}
                                    }
                                }
                            }
                        },
                        "headers": {
                            "X-Request-Id": {
                                "$ref": "#/components/headers/X-Request-Id"
                            },
                            "PalomaPOS-Api-Version": {
                                "$ref": "#/components/headers/PalomaPOS-Api-Version"
                            }
                        }
                    },
                    "403": {
                        "description": "insufficient_scope / not_owner",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                },
                                "example": {
                                    "error": {
                                        "code": "insufficient_scope",
                                        "message": "The access token does not grant the scope required by this operation.",
                                        "retryable": false,
                                        "request_id": "req_4f1c2a9be07d5e8a1b3c6d20",
                                        "details": {
                                            "required_scope": "reports:read"
                                        }
                                    }
                                }
                            }
                        },
                        "headers": {
                            "X-Request-Id": {
                                "$ref": "#/components/headers/X-Request-Id"
                            },
                            "PalomaPOS-Api-Version": {
                                "$ref": "#/components/headers/PalomaPOS-Api-Version"
                            }
                        }
                    },
                    "429": {
                        "description": "rate_limited",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                },
                                "example": {
                                    "error": {
                                        "code": "rate_limited",
                                        "message": "Rate limit exceeded: 600 read requests per minute for this app and account.",
                                        "retryable": true,
                                        "request_id": "req_4f1c2a9be07d5e8a1b3c6d20",
                                        "details": {
                                            "limit": 600,
                                            "kind": "read",
                                            "retry_after": 17
                                        }
                                    }
                                }
                            }
                        },
                        "headers": {
                            "Retry-After": {
                                "$ref": "#/components/headers/Retry-After"
                            },
                            "X-Request-Id": {
                                "$ref": "#/components/headers/X-Request-Id"
                            },
                            "PalomaPOS-Api-Version": {
                                "$ref": "#/components/headers/PalomaPOS-Api-Version"
                            }
                        }
                    },
                    "500": {
                        "$ref": "#/components/responses/InternalError"
                    },
                    "503": {
                        "description": "temporarily_unavailable — another report of this account is being built, or the report exceeded its time limit · or `account_not_ready` (not retryable): this business account's database has not been upgraded for the API yet",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                },
                                "example": {
                                    "error": {
                                        "code": "temporarily_unavailable",
                                        "message": "Another sales report for this account is still being built. Retry in a few seconds.",
                                        "retryable": true,
                                        "request_id": "req_4f1c2a9be07d5e8a1b3c6d20",
                                        "details": {}
                                    }
                                }
                            }
                        },
                        "headers": {
                            "Retry-After": {
                                "$ref": "#/components/headers/Retry-After"
                            },
                            "X-Request-Id": {
                                "$ref": "#/components/headers/X-Request-Id"
                            },
                            "PalomaPOS-Api-Version": {
                                "$ref": "#/components/headers/PalomaPOS-Api-Version"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "from",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string",
                            "format": "date"
                        },
                        "description": "First day, inclusive (YYYY-MM-DD, the locations' calendar)."
                    },
                    {
                        "name": "to",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string",
                            "format": "date"
                        },
                        "description": "Last day, inclusive (YYYY-MM-DD); at most 92 days after `from` counting both ends."
                    },
                    {
                        "name": "location_id",
                        "in": "query",
                        "schema": {
                            "type": "string"
                        },
                        "description": "Only this location."
                    }
                ],
                "operationId": "getReportsSalesDaily",
                "description": "Sales per day, location and item for a period of at most 92 days (see `SalesDay` for what is counted). Days without closed orders are omitted. One report per account is built at a time and each query has a time limit; a busy account or a query over the limit answers `503 temporarily_unavailable` with `Retry-After` — retry, or ask for a shorter period."
            }
        },
        "/payment-sessions/{id}": {
            "get": {
                "summary": "Get a payment session",
                "operationId": "getPaymentSession",
                "tags": [
                    "Payments"
                ],
                "security": [
                    {
                        "oauth2": [
                            "payments:process"
                        ]
                    }
                ],
                "x-palomapos-phase": "payments",
                "description": "A payment session that PalomaPOS sent to the calling app for the connected account. Use it to check whether your resolve reached PalomaPOS. Another app's session, or an unknown id, is `404`.",
                "parameters": [
                    {
                        "name": "id",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "string",
                            "pattern": "^pps_[0-9a-f]{32}$"
                        },
                        "description": "Payment session id from the `payment_session.create` request (`pps_…`)."
                    }
                ],
                "responses": {
                    "200": {
                        "description": "The payment session",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/PaymentSession"
                                },
                                "example": {
                                    "id": "pps_3f9a1c2b7d4e6f8091a2b3c4d5e6f708",
                                    "status": "paid",
                                    "amount": "5000.00",
                                    "currency": "KZT",
                                    "order_id": "10432",
                                    "location_id": "3",
                                    "reference": "inv_88213",
                                    "settlement": "applied",
                                    "settlement_reason": null,
                                    "failure_code": null,
                                    "created_at": "2026-10-18T12:00:02+05:00",
                                    "expires_at": "2026-10-18T12:15:02+05:00",
                                    "resolved_at": "2026-10-18T12:03:41+05:00"
                                }
                            }
                        },
                        "headers": {
                            "X-Request-Id": {
                                "$ref": "#/components/headers/X-Request-Id"
                            },
                            "PalomaPOS-Api-Version": {
                                "$ref": "#/components/headers/PalomaPOS-Api-Version"
                            },
                            "Idempotent-Replayed": {
                                "$ref": "#/components/headers/Idempotent-Replayed"
                            }
                        }
                    },
                    "401": {
                        "description": "invalid_token",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                },
                                "example": {
                                    "error": {
                                        "code": "invalid_token",
                                        "message": "The access token is missing, expired or revoked.",
                                        "retryable": false,
                                        "request_id": "req_4f1c2a9be07d5e8a1b3c6d20",
                                        "details": {}
                                    }
                                }
                            }
                        },
                        "headers": {
                            "X-Request-Id": {
                                "$ref": "#/components/headers/X-Request-Id"
                            },
                            "PalomaPOS-Api-Version": {
                                "$ref": "#/components/headers/PalomaPOS-Api-Version"
                            }
                        }
                    },
                    "403": {
                        "description": "insufficient_scope (payments:process)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                },
                                "examples": {
                                    "insufficient_scope": {
                                        "summary": "insufficient_scope",
                                        "value": {
                                            "error": {
                                                "code": "insufficient_scope",
                                                "message": "The access token does not grant the scope this method requires.",
                                                "retryable": false,
                                                "request_id": "req_4f1c2a9be07d5e8a1b3c6d20",
                                                "details": {
                                                    "required_scope": "payments:process"
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        },
                        "headers": {
                            "X-Request-Id": {
                                "$ref": "#/components/headers/X-Request-Id"
                            },
                            "PalomaPOS-Api-Version": {
                                "$ref": "#/components/headers/PalomaPOS-Api-Version"
                            }
                        }
                    },
                    "404": {
                        "description": "not_found — no such session for this app and account (also when payment providers are switched off on the market)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                },
                                "examples": {
                                    "not_found": {
                                        "summary": "not_found",
                                        "value": {
                                            "error": {
                                                "code": "not_found",
                                                "message": "Payment session not found.",
                                                "retryable": false,
                                                "request_id": "req_4f1c2a9be07d5e8a1b3c6d20",
                                                "details": {}
                                            }
                                        }
                                    }
                                }
                            }
                        },
                        "headers": {
                            "X-Request-Id": {
                                "$ref": "#/components/headers/X-Request-Id"
                            },
                            "PalomaPOS-Api-Version": {
                                "$ref": "#/components/headers/PalomaPOS-Api-Version"
                            }
                        }
                    },
                    "429": {
                        "description": "rate_limited",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                },
                                "example": {
                                    "error": {
                                        "code": "rate_limited",
                                        "message": "Rate limit exceeded: 600 read requests per minute for this app and account.",
                                        "retryable": true,
                                        "request_id": "req_4f1c2a9be07d5e8a1b3c6d20",
                                        "details": {
                                            "limit": 600,
                                            "kind": "read",
                                            "retry_after": 23
                                        }
                                    }
                                }
                            }
                        },
                        "headers": {
                            "Retry-After": {
                                "$ref": "#/components/headers/Retry-After"
                            },
                            "X-Request-Id": {
                                "$ref": "#/components/headers/X-Request-Id"
                            },
                            "PalomaPOS-Api-Version": {
                                "$ref": "#/components/headers/PalomaPOS-Api-Version"
                            }
                        }
                    },
                    "500": {
                        "$ref": "#/components/responses/InternalError"
                    },
                    "503": {
                        "description": "temporarily_unavailable — the order is being changed by another request; retry with the same key · or `account_not_ready` (not retryable): this business account's database has not been upgraded for the API yet",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                },
                                "example": {
                                    "error": {
                                        "code": "temporarily_unavailable",
                                        "message": "The service is temporarily unavailable. Retry later.",
                                        "retryable": true,
                                        "request_id": "req_4f1c2a9be07d5e8a1b3c6d20",
                                        "details": {}
                                    }
                                }
                            }
                        },
                        "headers": {
                            "Retry-After": {
                                "$ref": "#/components/headers/Retry-After"
                            },
                            "X-Request-Id": {
                                "$ref": "#/components/headers/X-Request-Id"
                            },
                            "PalomaPOS-Api-Version": {
                                "$ref": "#/components/headers/PalomaPOS-Api-Version"
                            }
                        }
                    }
                }
            }
        },
        "/payment-sessions/{id}/resolve": {
            "post": {
                "summary": "Confirm that the guest paid",
                "operationId": "resolvePaymentSession",
                "tags": [
                    "Payments"
                ],
                "security": [
                    {
                        "oauth2": [
                            "payments:process"
                        ]
                    }
                ],
                "x-palomapos-phase": "payments",
                "description": "Call this from your server when the payment is final (money taken). `amount` must equal the session amount exactly. PalomaPOS records the payment on the order with your app's payment type and closes it (status `paid`, `settlement: applied`). A late payment for a session past `expires_at` is accepted too, and so is a superseded session (`failed`, `failure_code: superseded`) the guest paid anyway. If the order can no longer take this payment — cancelled or closed on the POS, or its total changed — the money is still recorded on the session (`paid`, `settlement: not_applied`, `settlement_reason`), the owner sees it in the dashboard, and you refund the guest. Retrying with the same `reference` returns the same session; a different reference for a paid session is `409 invalid_state`.",
                "parameters": [
                    {
                        "name": "id",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "string",
                            "pattern": "^pps_[0-9a-f]{32}$"
                        },
                        "description": "Payment session id from the `payment_session.create` request (`pps_…`)."
                    },
                    {
                        "name": "Idempotency-Key",
                        "in": "header",
                        "required": true,
                        "schema": {
                            "type": "string",
                            "maxLength": 64
                        },
                        "description": "Required. 1–64 printable ASCII characters, case-sensitive, scoped to the app and account, kept 24 h. The same key with the same request (method, path, query, JSON body regardless of key order and whitespace) returns the stored response with header `Idempotent-Replayed: true`; with a different request — 409 idempotency_key_reused. While the first request with this key is still running — 409 idempotency_in_progress (retryable, Retry-After: 1). Responses to 400, 429 and 5xx are not stored: retrying with the same key runs the operation again."
                    }
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/PaymentSessionResolveInput"
                            },
                            "example": {
                                "reference": "inv_88213",
                                "amount": "5000.00"
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "The session — paid, with the settlement outcome",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/PaymentSession"
                                },
                                "example": {
                                    "id": "pps_3f9a1c2b7d4e6f8091a2b3c4d5e6f708",
                                    "status": "paid",
                                    "amount": "5000.00",
                                    "currency": "KZT",
                                    "order_id": "10432",
                                    "location_id": "3",
                                    "reference": "inv_88213",
                                    "settlement": "applied",
                                    "settlement_reason": null,
                                    "failure_code": null,
                                    "created_at": "2026-10-18T12:00:02+05:00",
                                    "expires_at": "2026-10-18T12:15:02+05:00",
                                    "resolved_at": "2026-10-18T12:03:41+05:00"
                                }
                            }
                        },
                        "headers": {
                            "X-Request-Id": {
                                "$ref": "#/components/headers/X-Request-Id"
                            },
                            "PalomaPOS-Api-Version": {
                                "$ref": "#/components/headers/PalomaPOS-Api-Version"
                            },
                            "Idempotent-Replayed": {
                                "$ref": "#/components/headers/Idempotent-Replayed"
                            }
                        }
                    },
                    "400": {
                        "description": "invalid_request — details.fields: reference, amount",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                },
                                "examples": {
                                    "invalid_request": {
                                        "summary": "invalid_request",
                                        "value": {
                                            "error": {
                                                "code": "invalid_request",
                                                "message": "The request body is invalid: see details.fields.",
                                                "retryable": false,
                                                "request_id": "req_4f1c2a9be07d5e8a1b3c6d20",
                                                "details": {
                                                    "fields": {
                                                        "amount": "required"
                                                    }
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        },
                        "headers": {
                            "X-Request-Id": {
                                "$ref": "#/components/headers/X-Request-Id"
                            },
                            "PalomaPOS-Api-Version": {
                                "$ref": "#/components/headers/PalomaPOS-Api-Version"
                            }
                        }
                    },
                    "401": {
                        "description": "invalid_token",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                },
                                "example": {
                                    "error": {
                                        "code": "invalid_token",
                                        "message": "The access token is missing, expired or revoked.",
                                        "retryable": false,
                                        "request_id": "req_4f1c2a9be07d5e8a1b3c6d20",
                                        "details": {}
                                    }
                                }
                            }
                        },
                        "headers": {
                            "X-Request-Id": {
                                "$ref": "#/components/headers/X-Request-Id"
                            },
                            "PalomaPOS-Api-Version": {
                                "$ref": "#/components/headers/PalomaPOS-Api-Version"
                            }
                        }
                    },
                    "403": {
                        "description": "insufficient_scope (payments:process)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                },
                                "examples": {
                                    "insufficient_scope": {
                                        "summary": "insufficient_scope",
                                        "value": {
                                            "error": {
                                                "code": "insufficient_scope",
                                                "message": "The access token does not grant the scope this method requires.",
                                                "retryable": false,
                                                "request_id": "req_4f1c2a9be07d5e8a1b3c6d20",
                                                "details": {
                                                    "required_scope": "payments:process"
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        },
                        "headers": {
                            "X-Request-Id": {
                                "$ref": "#/components/headers/X-Request-Id"
                            },
                            "PalomaPOS-Api-Version": {
                                "$ref": "#/components/headers/PalomaPOS-Api-Version"
                            }
                        }
                    },
                    "404": {
                        "description": "not_found — no such session for this app and account (also when payment providers are switched off on the market)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                },
                                "examples": {
                                    "not_found": {
                                        "summary": "not_found",
                                        "value": {
                                            "error": {
                                                "code": "not_found",
                                                "message": "Payment session not found.",
                                                "retryable": false,
                                                "request_id": "req_4f1c2a9be07d5e8a1b3c6d20",
                                                "details": {}
                                            }
                                        }
                                    }
                                }
                            }
                        },
                        "headers": {
                            "X-Request-Id": {
                                "$ref": "#/components/headers/X-Request-Id"
                            },
                            "PalomaPOS-Api-Version": {
                                "$ref": "#/components/headers/PalomaPOS-Api-Version"
                            }
                        }
                    },
                    "409": {
                        "description": "total_mismatch — details.expected (session amount), details.actual; invalid_state — details.reason: already_paid | not_payable | concurrent_change | test_session_unavailable (sandbox), details.status; idempotency_key_reused / idempotency_in_progress",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                },
                                "examples": {
                                    "total_mismatch": {
                                        "summary": "total_mismatch",
                                        "value": {
                                            "error": {
                                                "code": "total_mismatch",
                                                "message": "amount must equal the amount of the payment session.",
                                                "retryable": false,
                                                "request_id": "req_4f1c2a9be07d5e8a1b3c6d20",
                                                "details": {
                                                    "expected": "5000.00",
                                                    "actual": "4999.99"
                                                }
                                            }
                                        }
                                    },
                                    "invalid_state": {
                                        "summary": "invalid_state",
                                        "value": {
                                            "error": {
                                                "code": "invalid_state",
                                                "message": "The payment session cannot be paid in its current status.",
                                                "retryable": false,
                                                "request_id": "req_4f1c2a9be07d5e8a1b3c6d20",
                                                "details": {
                                                    "reason": "not_payable",
                                                    "status": "rejected"
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        },
                        "headers": {
                            "X-Request-Id": {
                                "$ref": "#/components/headers/X-Request-Id"
                            },
                            "PalomaPOS-Api-Version": {
                                "$ref": "#/components/headers/PalomaPOS-Api-Version"
                            }
                        }
                    },
                    "429": {
                        "description": "rate_limited",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                },
                                "example": {
                                    "error": {
                                        "code": "rate_limited",
                                        "message": "Rate limit exceeded: 60 write requests per minute for this app and account.",
                                        "retryable": true,
                                        "request_id": "req_4f1c2a9be07d5e8a1b3c6d20",
                                        "details": {
                                            "limit": 60,
                                            "kind": "write",
                                            "retry_after": 23
                                        }
                                    }
                                }
                            }
                        },
                        "headers": {
                            "Retry-After": {
                                "$ref": "#/components/headers/Retry-After"
                            },
                            "X-Request-Id": {
                                "$ref": "#/components/headers/X-Request-Id"
                            },
                            "PalomaPOS-Api-Version": {
                                "$ref": "#/components/headers/PalomaPOS-Api-Version"
                            }
                        }
                    },
                    "500": {
                        "$ref": "#/components/responses/InternalError"
                    },
                    "503": {
                        "description": "temporarily_unavailable — the order is being changed by another request; retry with the same key · or `account_not_ready` (not retryable): this business account's database has not been upgraded for the API yet",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                },
                                "example": {
                                    "error": {
                                        "code": "temporarily_unavailable",
                                        "message": "The service is temporarily unavailable. Retry later.",
                                        "retryable": true,
                                        "request_id": "req_4f1c2a9be07d5e8a1b3c6d20",
                                        "details": {}
                                    }
                                }
                            }
                        },
                        "headers": {
                            "Retry-After": {
                                "$ref": "#/components/headers/Retry-After"
                            },
                            "X-Request-Id": {
                                "$ref": "#/components/headers/X-Request-Id"
                            },
                            "PalomaPOS-Api-Version": {
                                "$ref": "#/components/headers/PalomaPOS-Api-Version"
                            }
                        }
                    }
                }
            }
        },
        "/payment-sessions/{id}/reject": {
            "post": {
                "summary": "Report that the payment will not happen",
                "operationId": "rejectPaymentSession",
                "tags": [
                    "Payments"
                ],
                "security": [
                    {
                        "oauth2": [
                            "payments:process"
                        ]
                    }
                ],
                "x-palomapos-phase": "payments",
                "description": "The guest declined, the payment failed or your invoice was cancelled. The guest sees that the payment did not go through and may start again (a new session). Rejecting a rejected session again returns it unchanged; a paid session — or one whose payment PalomaPOS has already recorded — is `409 invalid_state` with `details.reason: already_paid` (do not refund it).",
                "parameters": [
                    {
                        "name": "id",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "string",
                            "pattern": "^pps_[0-9a-f]{32}$"
                        },
                        "description": "Payment session id from the `payment_session.create` request (`pps_…`)."
                    },
                    {
                        "name": "Idempotency-Key",
                        "in": "header",
                        "required": true,
                        "schema": {
                            "type": "string",
                            "maxLength": 64
                        },
                        "description": "Required. 1–64 printable ASCII characters, case-sensitive, scoped to the app and account, kept 24 h. The same key with the same request (method, path, query, JSON body regardless of key order and whitespace) returns the stored response with header `Idempotent-Replayed: true`; with a different request — 409 idempotency_key_reused. While the first request with this key is still running — 409 idempotency_in_progress (retryable, Retry-After: 1). Responses to 400, 429 and 5xx are not stored: retrying with the same key runs the operation again."
                    }
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/PaymentSessionRejectInput"
                            },
                            "example": {
                                "reason": "declined"
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "The session — rejected",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/PaymentSession"
                                },
                                "example": {
                                    "id": "pps_3f9a1c2b7d4e6f8091a2b3c4d5e6f708",
                                    "status": "rejected",
                                    "amount": "5000.00",
                                    "currency": "KZT",
                                    "order_id": "10432",
                                    "location_id": "3",
                                    "reference": "inv_88213",
                                    "settlement": null,
                                    "settlement_reason": null,
                                    "failure_code": "declined",
                                    "created_at": "2026-10-18T12:00:02+05:00",
                                    "expires_at": "2026-10-18T12:15:02+05:00",
                                    "resolved_at": "2026-10-18T12:03:41+05:00"
                                }
                            }
                        },
                        "headers": {
                            "X-Request-Id": {
                                "$ref": "#/components/headers/X-Request-Id"
                            },
                            "PalomaPOS-Api-Version": {
                                "$ref": "#/components/headers/PalomaPOS-Api-Version"
                            },
                            "Idempotent-Replayed": {
                                "$ref": "#/components/headers/Idempotent-Replayed"
                            }
                        }
                    },
                    "400": {
                        "description": "invalid_request — details.fields.reason",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                },
                                "examples": {
                                    "invalid_request": {
                                        "summary": "invalid_request",
                                        "value": {
                                            "error": {
                                                "code": "invalid_request",
                                                "message": "The request body is invalid: see details.fields.",
                                                "retryable": false,
                                                "request_id": "req_4f1c2a9be07d5e8a1b3c6d20",
                                                "details": {
                                                    "fields": {
                                                        "reason": "must_be_one_of:declined|cancelled|expired|error"
                                                    }
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        },
                        "headers": {
                            "X-Request-Id": {
                                "$ref": "#/components/headers/X-Request-Id"
                            },
                            "PalomaPOS-Api-Version": {
                                "$ref": "#/components/headers/PalomaPOS-Api-Version"
                            }
                        }
                    },
                    "401": {
                        "description": "invalid_token",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                },
                                "example": {
                                    "error": {
                                        "code": "invalid_token",
                                        "message": "The access token is missing, expired or revoked.",
                                        "retryable": false,
                                        "request_id": "req_4f1c2a9be07d5e8a1b3c6d20",
                                        "details": {}
                                    }
                                }
                            }
                        },
                        "headers": {
                            "X-Request-Id": {
                                "$ref": "#/components/headers/X-Request-Id"
                            },
                            "PalomaPOS-Api-Version": {
                                "$ref": "#/components/headers/PalomaPOS-Api-Version"
                            }
                        }
                    },
                    "403": {
                        "description": "insufficient_scope (payments:process)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                },
                                "examples": {
                                    "insufficient_scope": {
                                        "summary": "insufficient_scope",
                                        "value": {
                                            "error": {
                                                "code": "insufficient_scope",
                                                "message": "The access token does not grant the scope this method requires.",
                                                "retryable": false,
                                                "request_id": "req_4f1c2a9be07d5e8a1b3c6d20",
                                                "details": {
                                                    "required_scope": "payments:process"
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        },
                        "headers": {
                            "X-Request-Id": {
                                "$ref": "#/components/headers/X-Request-Id"
                            },
                            "PalomaPOS-Api-Version": {
                                "$ref": "#/components/headers/PalomaPOS-Api-Version"
                            }
                        }
                    },
                    "404": {
                        "description": "not_found — no such session for this app and account (also when payment providers are switched off on the market)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                },
                                "examples": {
                                    "not_found": {
                                        "summary": "not_found",
                                        "value": {
                                            "error": {
                                                "code": "not_found",
                                                "message": "Payment session not found.",
                                                "retryable": false,
                                                "request_id": "req_4f1c2a9be07d5e8a1b3c6d20",
                                                "details": {}
                                            }
                                        }
                                    }
                                }
                            }
                        },
                        "headers": {
                            "X-Request-Id": {
                                "$ref": "#/components/headers/X-Request-Id"
                            },
                            "PalomaPOS-Api-Version": {
                                "$ref": "#/components/headers/PalomaPOS-Api-Version"
                            }
                        }
                    },
                    "409": {
                        "description": "invalid_state — details.reason: already_paid | not_rejectable | test_session_unavailable (sandbox)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                },
                                "examples": {
                                    "invalid_state": {
                                        "summary": "invalid_state",
                                        "value": {
                                            "error": {
                                                "code": "invalid_state",
                                                "message": "The payment session cannot be rejected in its current status.",
                                                "retryable": false,
                                                "request_id": "req_4f1c2a9be07d5e8a1b3c6d20",
                                                "details": {
                                                    "reason": "already_paid",
                                                    "status": "paid"
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        },
                        "headers": {
                            "X-Request-Id": {
                                "$ref": "#/components/headers/X-Request-Id"
                            },
                            "PalomaPOS-Api-Version": {
                                "$ref": "#/components/headers/PalomaPOS-Api-Version"
                            }
                        }
                    },
                    "429": {
                        "description": "rate_limited",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                },
                                "example": {
                                    "error": {
                                        "code": "rate_limited",
                                        "message": "Rate limit exceeded: 60 write requests per minute for this app and account.",
                                        "retryable": true,
                                        "request_id": "req_4f1c2a9be07d5e8a1b3c6d20",
                                        "details": {
                                            "limit": 60,
                                            "kind": "write",
                                            "retry_after": 23
                                        }
                                    }
                                }
                            }
                        },
                        "headers": {
                            "Retry-After": {
                                "$ref": "#/components/headers/Retry-After"
                            },
                            "X-Request-Id": {
                                "$ref": "#/components/headers/X-Request-Id"
                            },
                            "PalomaPOS-Api-Version": {
                                "$ref": "#/components/headers/PalomaPOS-Api-Version"
                            }
                        }
                    },
                    "500": {
                        "$ref": "#/components/responses/InternalError"
                    },
                    "503": {
                        "description": "temporarily_unavailable — the order is being changed by another request; retry with the same key · or `account_not_ready` (not retryable): this business account's database has not been upgraded for the API yet",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                },
                                "example": {
                                    "error": {
                                        "code": "temporarily_unavailable",
                                        "message": "The service is temporarily unavailable. Retry later.",
                                        "retryable": true,
                                        "request_id": "req_4f1c2a9be07d5e8a1b3c6d20",
                                        "details": {}
                                    }
                                }
                            }
                        },
                        "headers": {
                            "Retry-After": {
                                "$ref": "#/components/headers/Retry-After"
                            },
                            "X-Request-Id": {
                                "$ref": "#/components/headers/X-Request-Id"
                            },
                            "PalomaPOS-Api-Version": {
                                "$ref": "#/components/headers/PalomaPOS-Api-Version"
                            }
                        }
                    }
                }
            }
        },
        "/sandbox/payment-sessions": {
            "post": {
                "summary": "Sandbox: send me a test payment session",
                "operationId": "createSandboxPaymentSession",
                "tags": [
                    "Payments"
                ],
                "security": [
                    {
                        "oauth2": [
                            "payments:process"
                        ]
                    }
                ],
                "x-palomapos-phase": "payments",
                "x-palomapos-sandbox": true,
                "description": "**Sandbox host only** (`https://sandbox-api.paloma365.com/platform/v1`; on production hosts this path is `404`). Creates a test order for the account of the token and sends its payment session to your `session_url` right now — the very request production sends (`payment_session.create`, signed, `\"test\": true`). No QR menu, guest or real order is involved. The response carries the session, the test order, the exact request we sent (re-compute the signature from `delivery.request.body` if yours does not match) and three checks of your endpoint:\n\n- `signature` — the same request with an INVALID `PalomaPOS-Signature` was sent first and must get `401` (any 4xx);\n- `response` — your answer to the real request is a 2xx that follows the contract (`reference`, `action`, `expires_at`); otherwise the session is `failed` and `detail` says why;\n- `retry` — the same session sent again got the same `reference`.\n\nThen resolve or reject the session with `POST /v1/payment-sessions/{id}/resolve|reject` exactly as in production. `settlement` decides what resolving it does: `applied` (default — the order takes the payment) or a reason the order cannot take it anymore (`order_cancelled`, `order_closed`, `amount_changed`, `order_not_found`) — the answer is then `settlement: not_applied`, the branch where your service refunds the guest. `replaces` supersedes your own waiting test session (`failed`, `failure_code: superseded`) and sends a new one for the same test order — like a POS that changed the order total. `replaces` needs a new `amount` (a POS replaces a session only when the total changed). Nothing is written to the business's orders. Up to three requests to your URL, 8 seconds each; if the first gets no answer, the others are not sent. One test session of your app at a time (`503 temporarily_unavailable` while one is being delivered — retry in a few seconds) and at most 500 per 24 hours (`429`).",
                "parameters": [
                    {
                        "name": "Idempotency-Key",
                        "in": "header",
                        "required": true,
                        "schema": {
                            "type": "string",
                            "maxLength": 64
                        },
                        "description": "Required. 1–64 printable ASCII characters, case-sensitive, scoped to the app and account, kept 24 h. The same key with the same request (method, path, query, JSON body regardless of key order and whitespace) returns the stored response with header `Idempotent-Replayed: true`; with a different request — 409 idempotency_key_reused. While the first request with this key is still running — 409 idempotency_in_progress (retryable, Retry-After: 1). Responses to 400, 429 and 5xx are not stored: retrying with the same key runs the operation again."
                    }
                ],
                "requestBody": {
                    "required": false,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/SandboxPaymentSessionInput"
                            },
                            "examples": {
                                "applied": {
                                    "summary": "A session the order takes",
                                    "value": {
                                        "amount": "1000.00"
                                    }
                                },
                                "refund": {
                                    "summary": "The order was cancelled meanwhile: resolving gives not_applied",
                                    "value": {
                                        "settlement": "order_cancelled"
                                    }
                                },
                                "supersede": {
                                    "summary": "Replace a waiting test session (new total)",
                                    "value": {
                                        "replaces": "pps_7c1e9a2b4d6f8091a2b3c4d5e6f70812",
                                        "amount": "1200.00"
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "The test session (pending, or failed when your endpoint did not answer per contract), the test order, the request we sent and the checks",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/SandboxPaymentSessionResult"
                                },
                                "example": {
                                    "session": {
                                        "id": "pps_7c1e9a2b4d6f8091a2b3c4d5e6f70812",
                                        "status": "pending",
                                        "amount": "1000.00",
                                        "currency": "KZT",
                                        "order_id": "58",
                                        "location_id": "1",
                                        "reference": "inv_test_58",
                                        "settlement": null,
                                        "settlement_reason": null,
                                        "failure_code": null,
                                        "created_at": "2026-10-18T12:00:02+05:00",
                                        "expires_at": "2026-10-18T12:15:02+05:00",
                                        "resolved_at": null
                                    },
                                    "test_order": {
                                        "id": "58",
                                        "number": "TEST-58",
                                        "type": "pickup",
                                        "settlement": "applied"
                                    },
                                    "delivery": {
                                        "request": {
                                            "url": "https://api.example-pay.kz/palomapos/sessions",
                                            "headers": {
                                                "Content-Type": "application/json",
                                                "Accept": "application/json",
                                                "User-Agent": "PalomaPOS-Platform/1",
                                                "Idempotency-Key": "pps_7c1e9a2b4d6f8091a2b3c4d5e6f70812",
                                                "PalomaPOS-Api-Version": "1",
                                                "PalomaPOS-Signature": "t=1760770802,v1=9b8f…"
                                            },
                                            "body": "{\"type\":\"payment_session.create\",\"api_version\":\"1\",\"id\":\"pps_7c1e9a2b4d6f8091a2b3c4d5e6f70812\",\"created_at\":\"2026-10-18T07:00:02Z\",\"expires_at\":\"2026-10-18T07:15:02Z\",\"test\":true,\"account_id\":\"12345\",\"location_id\":\"1\",\"order\":{\"id\":\"58\",\"number\":\"TEST-58\",\"type\":\"pickup\"},\"amount\":\"1000.00\",\"currency\":\"KZT\",\"description\":\"Заказ №TEST-58\"}"
                                        },
                                        "checks": {
                                            "signature": {
                                                "result": "passed",
                                                "detail": null
                                            },
                                            "response": {
                                                "result": "passed",
                                                "detail": null
                                            },
                                            "retry": {
                                                "result": "passed",
                                                "detail": null
                                            }
                                        }
                                    }
                                }
                            }
                        },
                        "headers": {
                            "X-Request-Id": {
                                "$ref": "#/components/headers/X-Request-Id"
                            },
                            "PalomaPOS-Api-Version": {
                                "$ref": "#/components/headers/PalomaPOS-Api-Version"
                            },
                            "Idempotent-Replayed": {
                                "$ref": "#/components/headers/Idempotent-Replayed"
                            }
                        }
                    },
                    "400": {
                        "description": "invalid_request — details.fields: amount (must_be_positive_money, required_with_replaces, must_differ_from_the_replaced_session), order_type, settlement, replaces, checks, or an unknown field",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                },
                                "examples": {
                                    "invalid_request": {
                                        "summary": "invalid_request",
                                        "value": {
                                            "error": {
                                                "code": "invalid_request",
                                                "message": "The request body is invalid: see details.fields.",
                                                "retryable": false,
                                                "request_id": "req_4f1c2a9be07d5e8a1b3c6d20",
                                                "details": {
                                                    "fields": {
                                                        "settlement": "must_be_one_of:applied|order_cancelled|order_closed|amount_changed|order_not_found"
                                                    }
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        },
                        "headers": {
                            "X-Request-Id": {
                                "$ref": "#/components/headers/X-Request-Id"
                            },
                            "PalomaPOS-Api-Version": {
                                "$ref": "#/components/headers/PalomaPOS-Api-Version"
                            }
                        }
                    },
                    "401": {
                        "description": "invalid_token",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                },
                                "example": {
                                    "error": {
                                        "code": "invalid_token",
                                        "message": "The access token is missing, expired or revoked.",
                                        "retryable": false,
                                        "request_id": "req_4f1c2a9be07d5e8a1b3c6d20",
                                        "details": {}
                                    }
                                }
                            }
                        },
                        "headers": {
                            "X-Request-Id": {
                                "$ref": "#/components/headers/X-Request-Id"
                            },
                            "PalomaPOS-Api-Version": {
                                "$ref": "#/components/headers/PalomaPOS-Api-Version"
                            }
                        }
                    },
                    "403": {
                        "description": "insufficient_scope (payments:process)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                },
                                "examples": {
                                    "insufficient_scope": {
                                        "summary": "insufficient_scope",
                                        "value": {
                                            "error": {
                                                "code": "insufficient_scope",
                                                "message": "The access token does not grant the scope this method requires.",
                                                "retryable": false,
                                                "request_id": "req_4f1c2a9be07d5e8a1b3c6d20",
                                                "details": {
                                                    "required_scope": "payments:process"
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        },
                        "headers": {
                            "X-Request-Id": {
                                "$ref": "#/components/headers/X-Request-Id"
                            },
                            "PalomaPOS-Api-Version": {
                                "$ref": "#/components/headers/PalomaPOS-Api-Version"
                            }
                        }
                    },
                    "404": {
                        "description": "not_found — not the sandbox host (this operation exists only there), or payment providers are switched off",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                },
                                "examples": {
                                    "not_found": {
                                        "summary": "not_found",
                                        "value": {
                                            "error": {
                                                "code": "not_found",
                                                "message": "Unrecognized request URL (POST /platform/v1/sandbox/payment-sessions).",
                                                "retryable": false,
                                                "request_id": "req_4f1c2a9be07d5e8a1b3c6d20",
                                                "details": {}
                                            }
                                        }
                                    }
                                }
                            }
                        },
                        "headers": {
                            "X-Request-Id": {
                                "$ref": "#/components/headers/X-Request-Id"
                            },
                            "PalomaPOS-Api-Version": {
                                "$ref": "#/components/headers/PalomaPOS-Api-Version"
                            }
                        }
                    },
                    "409": {
                        "description": "provider_not_ready — details.reason: not_a_payment_provider | currency_unsupported | scope_missing | app_unavailable; invalid_state — details.reason: not_replaceable (only a waiting test session can be replaced); idempotency_key_reused / idempotency_in_progress",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                },
                                "examples": {
                                    "provider_not_ready": {
                                        "summary": "provider_not_ready",
                                        "value": {
                                            "error": {
                                                "code": "provider_not_ready",
                                                "message": "This app cannot take payments for this account yet: see details.reason.",
                                                "retryable": false,
                                                "request_id": "req_4f1c2a9be07d5e8a1b3c6d20",
                                                "details": {
                                                    "reason": "currency_unsupported"
                                                }
                                            }
                                        }
                                    },
                                    "invalid_state": {
                                        "summary": "invalid_state",
                                        "value": {
                                            "error": {
                                                "code": "invalid_state",
                                                "message": "Only a waiting test session (creating or pending) can be replaced.",
                                                "retryable": false,
                                                "request_id": "req_4f1c2a9be07d5e8a1b3c6d20",
                                                "details": {
                                                    "reason": "not_replaceable",
                                                    "status": "paid"
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        },
                        "headers": {
                            "X-Request-Id": {
                                "$ref": "#/components/headers/X-Request-Id"
                            },
                            "PalomaPOS-Api-Version": {
                                "$ref": "#/components/headers/PalomaPOS-Api-Version"
                            }
                        }
                    },
                    "429": {
                        "description": "rate_limited — the per-minute write limit of the connection, or the sandbox limit of 500 test sessions per app in 24 hours (`details.kind: sandbox_sessions`)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                },
                                "examples": {
                                    "per_minute": {
                                        "summary": "write limit",
                                        "value": {
                                            "error": {
                                                "code": "rate_limited",
                                                "message": "Rate limit exceeded: 60 write requests per minute for this app and account.",
                                                "retryable": true,
                                                "request_id": "req_4f1c2a9be07d5e8a1b3c6d20",
                                                "details": {
                                                    "limit": 60,
                                                    "kind": "write",
                                                    "retry_after": 23
                                                }
                                            }
                                        }
                                    },
                                    "daily": {
                                        "summary": "sandbox daily limit",
                                        "value": {
                                            "error": {
                                                "code": "rate_limited",
                                                "message": "Sandbox limit: 500 test sessions per app in 24 hours.",
                                                "retryable": true,
                                                "request_id": "req_4f1c2a9be07d5e8a1b3c6d20",
                                                "details": {
                                                    "limit": 500,
                                                    "kind": "sandbox_sessions",
                                                    "retry_after": 3600
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        },
                        "headers": {
                            "Retry-After": {
                                "$ref": "#/components/headers/Retry-After"
                            },
                            "X-Request-Id": {
                                "$ref": "#/components/headers/X-Request-Id"
                            },
                            "PalomaPOS-Api-Version": {
                                "$ref": "#/components/headers/PalomaPOS-Api-Version"
                            }
                        }
                    },
                    "500": {
                        "$ref": "#/components/responses/InternalError"
                    },
                    "503": {
                        "description": "temporarily_unavailable — another test session of your app is being delivered right now (retry in a few seconds) · not_configured — payment providers are not configured on this host",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                },
                                "examples": {
                                    "not_configured": {
                                        "summary": "not_configured",
                                        "value": {
                                            "error": {
                                                "code": "not_configured",
                                                "message": "Payment providers are not configured on this host.",
                                                "retryable": false,
                                                "request_id": "req_4f1c2a9be07d5e8a1b3c6d20",
                                                "details": {}
                                            }
                                        }
                                    },
                                    "temporarily_unavailable": {
                                        "summary": "temporarily_unavailable",
                                        "value": {
                                            "error": {
                                                "code": "temporarily_unavailable",
                                                "message": "Another test session of this app is being delivered. Retry in a few seconds.",
                                                "retryable": true,
                                                "request_id": "req_4f1c2a9be07d5e8a1b3c6d20",
                                                "details": {}
                                            }
                                        }
                                    }
                                }
                            }
                        },
                        "headers": {
                            "X-Request-Id": {
                                "$ref": "#/components/headers/X-Request-Id"
                            },
                            "PalomaPOS-Api-Version": {
                                "$ref": "#/components/headers/PalomaPOS-Api-Version"
                            }
                        }
                    }
                }
            }
        },
        "/sandbox/payment-readiness": {
            "get": {
                "summary": "Sandbox: what is left before production",
                "operationId": "getSandboxPaymentReadiness",
                "tags": [
                    "Payments"
                ],
                "security": [
                    {
                        "oauth2": [
                            "payments:process"
                        ]
                    }
                ],
                "x-palomapos-phase": "payments",
                "x-palomapos-sandbox": true,
                "description": "**Sandbox host only** (on production hosts this path is `404`). Grades your integration on the test account of the token: every check must be `passed` (`ready: true`) before you go live (create the production app in the market dashboard). `signature`, `session_response` and `retry` come from ONE session — your last test session with checks on (a fixed bug stops showing once a new session passes); `signature` passes only when the valid request of that same session passed too; `resolve_applied`, `resolve_not_applied` and `reject` pass once you have done each at least once. `next` is the first check that is not passed; each check says `how` to pass it. The same report is shown next to the app in Settings → Developers of the sandbox dashboard.",
                "responses": {
                    "200": {
                        "description": "The readiness report",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/SandboxReadiness"
                                },
                                "example": {
                                    "ready": false,
                                    "next": "resolve_not_applied",
                                    "checks": [
                                        {
                                            "id": "connection",
                                            "status": "passed",
                                            "detail": null,
                                            "checked_at": null,
                                            "how": "The owner of the test account connects your app with payments:process offline_access (OAuth, guide section 3); keep refreshing the token."
                                        },
                                        {
                                            "id": "signature",
                                            "status": "passed",
                                            "detail": null,
                                            "checked_at": "2026-10-18T12:00:02+05:00",
                                            "how": "POST /v1/sandbox/payment-sessions with checks on: a request with an invalid PalomaPOS-Signature must get 401 (any 4xx)."
                                        },
                                        {
                                            "id": "session_response",
                                            "status": "passed",
                                            "detail": null,
                                            "checked_at": "2026-10-18T12:00:02+05:00",
                                            "how": "POST /v1/sandbox/payment-sessions (checks on): answer within 8 seconds with a 2xx and {reference, action, expires_at} (guide section 9.6, step 3)."
                                        },
                                        {
                                            "id": "retry",
                                            "status": "passed",
                                            "detail": null,
                                            "checked_at": "2026-10-18T12:00:02+05:00",
                                            "how": "POST /v1/sandbox/payment-sessions with checks on: the same session id sent again must get the same reference."
                                        },
                                        {
                                            "id": "resolve_applied",
                                            "status": "passed",
                                            "detail": null,
                                            "checked_at": "2026-10-18T12:01:10+05:00",
                                            "how": "Create a test session (settlement \"applied\") and POST /v1/payment-sessions/{id}/resolve with its amount."
                                        },
                                        {
                                            "id": "resolve_not_applied",
                                            "status": "not_run",
                                            "detail": null,
                                            "checked_at": null,
                                            "how": "Create a test session with settlement \"order_cancelled\" and resolve it: the answer is settlement \"not_applied\" — your service refunds the guest."
                                        },
                                        {
                                            "id": "reject",
                                            "status": "not_run",
                                            "detail": null,
                                            "checked_at": null,
                                            "how": "Create a test session and POST /v1/payment-sessions/{id}/reject with a reason (declined, cancelled, expired, error)."
                                        }
                                    ]
                                }
                            }
                        },
                        "headers": {
                            "X-Request-Id": {
                                "$ref": "#/components/headers/X-Request-Id"
                            },
                            "PalomaPOS-Api-Version": {
                                "$ref": "#/components/headers/PalomaPOS-Api-Version"
                            }
                        }
                    },
                    "401": {
                        "description": "invalid_token",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                },
                                "example": {
                                    "error": {
                                        "code": "invalid_token",
                                        "message": "The access token is missing, expired or revoked.",
                                        "retryable": false,
                                        "request_id": "req_4f1c2a9be07d5e8a1b3c6d20",
                                        "details": {}
                                    }
                                }
                            }
                        },
                        "headers": {
                            "X-Request-Id": {
                                "$ref": "#/components/headers/X-Request-Id"
                            },
                            "PalomaPOS-Api-Version": {
                                "$ref": "#/components/headers/PalomaPOS-Api-Version"
                            }
                        }
                    },
                    "403": {
                        "description": "insufficient_scope (payments:process)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                },
                                "examples": {
                                    "insufficient_scope": {
                                        "summary": "insufficient_scope",
                                        "value": {
                                            "error": {
                                                "code": "insufficient_scope",
                                                "message": "The access token does not grant the scope this method requires.",
                                                "retryable": false,
                                                "request_id": "req_4f1c2a9be07d5e8a1b3c6d20",
                                                "details": {
                                                    "required_scope": "payments:process"
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        },
                        "headers": {
                            "X-Request-Id": {
                                "$ref": "#/components/headers/X-Request-Id"
                            },
                            "PalomaPOS-Api-Version": {
                                "$ref": "#/components/headers/PalomaPOS-Api-Version"
                            }
                        }
                    },
                    "404": {
                        "description": "not_found — not the sandbox host (this operation exists only there), or payment providers are switched off",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                },
                                "examples": {
                                    "not_found": {
                                        "summary": "not_found",
                                        "value": {
                                            "error": {
                                                "code": "not_found",
                                                "message": "Unrecognized request URL (GET /platform/v1/sandbox/payment-readiness).",
                                                "retryable": false,
                                                "request_id": "req_4f1c2a9be07d5e8a1b3c6d20",
                                                "details": {}
                                            }
                                        }
                                    }
                                }
                            }
                        },
                        "headers": {
                            "X-Request-Id": {
                                "$ref": "#/components/headers/X-Request-Id"
                            },
                            "PalomaPOS-Api-Version": {
                                "$ref": "#/components/headers/PalomaPOS-Api-Version"
                            }
                        }
                    },
                    "429": {
                        "description": "rate_limited",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                },
                                "example": {
                                    "error": {
                                        "code": "rate_limited",
                                        "message": "Rate limit exceeded: 600 read requests per minute for this app and account.",
                                        "retryable": true,
                                        "request_id": "req_4f1c2a9be07d5e8a1b3c6d20",
                                        "details": {
                                            "limit": 600,
                                            "kind": "read",
                                            "retry_after": 23
                                        }
                                    }
                                }
                            }
                        },
                        "headers": {
                            "Retry-After": {
                                "$ref": "#/components/headers/Retry-After"
                            },
                            "X-Request-Id": {
                                "$ref": "#/components/headers/X-Request-Id"
                            },
                            "PalomaPOS-Api-Version": {
                                "$ref": "#/components/headers/PalomaPOS-Api-Version"
                            }
                        }
                    },
                    "500": {
                        "$ref": "#/components/responses/InternalError"
                    },
                    "503": {
                        "$ref": "#/components/responses/Unavailable"
                    }
                }
            }
        }
    },
    "webhooks": {
        "event": {
            "post": {
                "summary": "Event notification to the app's webhook URL (later — until then use the since cursor)",
                "operationId": "receiveEvent",
                "security": [],
                "x-palomapos-phase": "later",
                "description": "Header `PalomaPOS-Signature: t=<unix>,v1=<hex>` where v1 = HMAC-SHA256(webhook_secret, \"<t>.<raw body>\"). Reject signatures older than 5 minutes. Reply 2xx fast; 429/5xx/timeouts are retried with backoff, other 4xx are dropped.",
                "parameters": [
                    {
                        "name": "PalomaPOS-Signature",
                        "in": "header",
                        "required": true,
                        "schema": {
                            "type": "string"
                        }
                    }
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/Event"
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Accepted"
                    }
                }
            }
        },
        "paymentSessionCreate": {
            "post": {
                "summary": "Payment session request to the payment provider's session URL",
                "operationId": "createPaymentSession",
                "security": [],
                "x-palomapos-phase": "payments",
                "description": "PalomaPOS calls the `session_url` registered for your payment provider app when a guest of a connected business starts paying a QR menu order. Verify `PalomaPOS-Signature: t=<unix>,v1=<hex>` where v1 = HMAC-SHA256(signing_secret, \"<t>.<raw body>\") (the `ppss_…` secret from your registration), compare in constant time and reject t older than 5 minutes. Answer within 8 seconds with 200/201 and a PaymentSessionCreateResponse; anything else fails the session and the guest is told online payment is unavailable. Do not take money on this call — create your invoice/QR and return it; report the outcome later with POST /payment-sessions/{id}/resolve or /reject. Redirects are not followed; only https on port 443 to a public address.",
                "parameters": [
                    {
                        "name": "PalomaPOS-Signature",
                        "in": "header",
                        "required": true,
                        "schema": {
                            "type": "string"
                        }
                    },
                    {
                        "name": "Idempotency-Key",
                        "in": "header",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Equals the session id."
                    }
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/PaymentSessionCreateRequest"
                            },
                            "example": {
                                "type": "payment_session.create",
                                "api_version": "1",
                                "id": "pps_3f9a1c2b7d4e6f8091a2b3c4d5e6f708",
                                "created_at": "2026-10-18T07:00:02Z",
                                "expires_at": "2026-10-18T07:15:02Z",
                                "test": false,
                                "account_id": "12345",
                                "location_id": "3",
                                "order": {
                                    "id": "10432",
                                    "number": "42",
                                    "type": "pickup"
                                },
                                "amount": "5000.00",
                                "currency": "KZT",
                                "description": "Заказ №42"
                            }
                        }
                    }
                },
                "responses": {
                    "201": {
                        "description": "Invoice created — what to show the guest",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/PaymentSessionCreateResponse"
                                },
                                "example": {
                                    "reference": "inv_88213",
                                    "action": {
                                        "type": "qr",
                                        "qr_payload": "https://pay.kaspi.kz/pay/abc123",
                                        "deep_links": [
                                            {
                                                "label": "Kaspi",
                                                "url": "https://kaspi.kz/pay/abc123"
                                            }
                                        ]
                                    },
                                    "expires_at": "2026-10-18T07:10:02Z"
                                }
                            }
                        }
                    }
                }
            }
        }
    },
    "components": {
        "securitySchemes": {
            "oauth2": {
                "type": "oauth2",
                "description": "Authorization Code + PKCE (S256, mandatory), confidential client: `client_secret_basic` or `client_secret_post` at the token and revocation endpoints. Consent is given by the account owner in the dashboard of the market; the granted scopes are the requested ones within the app's registered ceiling. Access token (`ppat_…`) lives 1 h. A refresh token (`pprt_…`, only with `offline_access`) is single-use and rotates on every refresh; it expires 90 days after it was issued, so access lasts while the app keeps refreshing. Presenting a spent refresh token again within 30 seconds returns the same new pair (safe retries and parallel refreshes); later it is treated as theft and revokes the whole grant. The token response also carries `scope` and `account_id` (string). Revocation: `POST /platform/oauth/revoke` (RFC 7009) — revoking a refresh token disconnects the app (the grant and all its tokens); revoking an access token revokes only that token. Endpoints are on the same host as the API of the market; there is no discovery document in v1. A business owner can also create a personal integration key for their own account in the dashboard — see the `personalKey` scheme; it calls the same endpoints.",
                "flows": {
                    "authorizationCode": {
                        "authorizationUrl": "/platform/oauth/authorize",
                        "tokenUrl": "/platform/oauth/token",
                        "refreshUrl": "/platform/oauth/token",
                        "scopes": {
                            "account:read": "Business profile, locations, hours, taxes, payment types",
                            "catalog:read": "Categories, items, modifiers, menus, stop list",
                            "orders:read": "All orders of the account (guest name/phone/address only with customers:read)",
                            "orders:write": "Create and cancel the app's own orders; price a cart (phase 3)",
                            "payments:write": "Mark the app's own orders as paid outside the POS",
                            "reports:read": "Aggregated sales reports",
                            "customers:read": "Customer base and guest personal data",
                            "staff:read": "Employees and shifts",
                            "offline_access": "Receive a refresh token (access keeps working while the app is used, until revoked)",
                            "payments:process": "Take payments for online orders as a payment provider: receive payment session requests and resolve them"
                        }
                    }
                }
            },
            "personalKey": {
                "type": "http",
                "scheme": "bearer",
                "description": "Personal integration key (`ppik_…`), created by the account owner in the dashboard (Connected apps → Create integration) for THEIR OWN account — no app registration and no OAuth. Send it exactly like an access token: `Authorization: Bearer ppik_…`. The owner picks the scopes when creating the key; every operation requires the same scopes as with `oauth2` (a missing one → 403 `insufficient_scope`). The key does not expire and is not refreshed: it works until the owner deletes it, then every request gets 401 `invalid_token`. It is shown once; only its hash is stored. `GET /v1/me` returns `app.kind = \"personal\"` and `token_expires_at = null` for it. Rate limits, idempotency and audit are the same as for apps."
            }
        },
        "schemas": {
            "Id": {
                "type": "string",
                "example": "10432",
                "description": "Stable identifier, always a string (numbers longer than 2^53 are never truncated)."
            },
            "Money": {
                "type": "string",
                "pattern": "^-?\\d+\\.\\d{2}$",
                "example": "12.50",
                "description": "Decimal amount in the account currency (USD, KZT, …), dot separator, always two decimals, never a float."
            },
            "Error": {
                "type": "object",
                "properties": {
                    "error": {
                        "type": "object",
                        "properties": {
                            "code": {
                                "type": "string",
                                "example": "insufficient_scope",
                                "description": "Stable, machine-readable. HTTP status → code (retryable in brackets): 400 invalid_request (details.fields); 401 invalid_token (+ WWW-Authenticate: Bearer error=\"invalid_token\"); 403 insufficient_scope (details.required_scope), not_owner; 404 not_found (also for routes that are switched off); 409 idempotency_key_reused, idempotency_in_progress [retryable, Retry-After], total_mismatch, invalid_state; 410 sync_token_expired; 422 item_unavailable, location_closed, fulfillment_disabled, quote_unsupported; 429 rate_limited [retryable, Retry-After]; 500 internal_error [retryable]; 503 temporarily_unavailable [retryable, Retry-After], account_not_ready (the business account's database has not been upgraded for the API yet — not retryable until PalomaPOS upgrades it; then the same request, even with the same Idempotency-Key, works). Codes are only ever added within v1."
                            },
                            "message": {
                                "type": "string"
                            },
                            "retryable": {
                                "type": "boolean",
                                "description": "true — the same request may succeed later (respect Retry-After when present)."
                            },
                            "request_id": {
                                "type": "string",
                                "description": "Same value as the X-Request-Id response header."
                            },
                            "details": {
                                "type": "object",
                                "additionalProperties": true
                            }
                        },
                        "required": [
                            "code",
                            "message",
                            "retryable",
                            "request_id"
                        ]
                    }
                },
                "required": [
                    "error"
                ]
            },
            "Me": {
                "type": "object",
                "properties": {
                    "app": {
                        "type": "object",
                        "properties": {
                            "client_id": {
                                "type": "string"
                            },
                            "name": {
                                "type": "string"
                            },
                            "kind": {
                                "type": "string",
                                "enum": [
                                    "app",
                                    "personal"
                                ],
                                "description": "`app` — an OAuth app (registered by its developer in the dashboard, or by the team); `personal` — a personal integration key of the account owner."
                            }
                        },
                        "required": [
                            "client_id",
                            "name",
                            "kind"
                        ]
                    },
                    "account_id": {
                        "$ref": "#/components/schemas/Id"
                    },
                    "scopes": {
                        "type": "array",
                        "items": {
                            "type": "string"
                        }
                    },
                    "token_expires_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "format": "date-time",
                        "description": "When the access token expires; `null` for a personal integration key (it has no expiry)."
                    }
                },
                "required": [
                    "app",
                    "account_id",
                    "scopes",
                    "token_expires_at"
                ]
            },
            "Account": {
                "type": "object",
                "properties": {
                    "id": {
                        "$ref": "#/components/schemas/Id"
                    },
                    "name": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "The account's display name as the owner registered it — the name the consent screen shows. There is no separate legal/business-name field; null when empty."
                    },
                    "currency": {
                        "type": "string",
                        "example": "USD",
                        "description": "ISO 4217 — the currency of every amount this API returns for the account."
                    },
                    "timezone": {
                        "type": "string",
                        "example": "America/New_York",
                        "description": "IANA time zone of the account; times are returned with its offset unless stated otherwise."
                    },
                    "country": {
                        "type": "string",
                        "example": "US",
                        "description": "ISO 3166-1 alpha-2 of the account's registration city. Without a city: the country of a single-country currency (KZT → KZ, UZS → UZ, KGS → KG, RUB → RU …), otherwise the market's home country (US on palomapos hosts, KZ on paloma365 hosts)."
                    },
                    "capabilities": {
                        "type": "object",
                        "description": "What this account can do through the API right now. Check it before offering a feature to the business instead of probing with a request.",
                        "properties": {
                            "order_writes": {
                                "type": "object",
                                "description": "Whether orders can be quoted and created for this account (`POST /orders/quote`, `POST /orders`). Per-location modes, minimum amounts and fees are in `GET /locations`.",
                                "properties": {
                                    "available": {
                                        "type": "boolean"
                                    },
                                    "reason": {
                                        "type": [
                                            "string",
                                            "null"
                                        ],
                                        "enum": [
                                            "not_launched",
                                            "pos_not_supported",
                                            null
                                        ],
                                        "description": "Why not, when `available` is false: `not_launched` — order writes are not switched on for this market yet (the write operations answer 404); `pos_not_supported` — the business runs a POS that cannot receive API orders (writes answer `422 fulfillment_disabled`, `details.reason = pos_not_supported`). New reasons may be added; treat an unknown one as unavailable."
                                    }
                                },
                                "required": [
                                    "available",
                                    "reason"
                                ]
                            }
                        },
                        "required": [
                            "order_writes"
                        ]
                    }
                },
                "required": [
                    "id",
                    "name",
                    "currency",
                    "timezone",
                    "country",
                    "capabilities"
                ]
            },
            "TimeInterval": {
                "type": "object",
                "properties": {
                    "opens": {
                        "type": "string",
                        "pattern": "^\\d{2}:\\d{2}$",
                        "example": "09:00"
                    },
                    "closes": {
                        "type": "string",
                        "pattern": "^\\d{2}:\\d{2}$",
                        "example": "22:00",
                        "description": "Earlier than `opens` — the interval ends on the next day (overnight)."
                    }
                },
                "required": [
                    "opens",
                    "closes"
                ]
            },
            "WeeklyHours": {
                "type": "object",
                "properties": {
                    "mon": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/TimeInterval"
                        }
                    },
                    "tue": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/TimeInterval"
                        }
                    },
                    "wed": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/TimeInterval"
                        }
                    },
                    "thu": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/TimeInterval"
                        }
                    },
                    "fri": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/TimeInterval"
                        }
                    },
                    "sat": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/TimeInterval"
                        }
                    },
                    "sun": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/TimeInterval"
                        }
                    }
                },
                "required": [
                    "mon",
                    "tue",
                    "wed",
                    "thu",
                    "fri",
                    "sat",
                    "sun"
                ],
                "description": "Local time of the location. Today PalomaPOS stores one working-day interval shared by all days (the location's \"working day start / end\"), so every day carries that same interval. The weekly shape is final and will carry real per-day intervals when the data model has them."
            },
            "Address": {
                "type": "object",
                "properties": {
                    "line1": {
                        "type": [
                            "string",
                            "null"
                        ]
                    },
                    "line2": {
                        "type": [
                            "string",
                            "null"
                        ]
                    },
                    "city": {
                        "type": [
                            "string",
                            "null"
                        ]
                    },
                    "region": {
                        "type": [
                            "string",
                            "null"
                        ]
                    },
                    "postal_code": {
                        "type": [
                            "string",
                            "null"
                        ]
                    },
                    "country": {
                        "type": [
                            "string",
                            "null"
                        ]
                    },
                    "formatted": {
                        "type": "string",
                        "description": "Always filled; the only field of an order's delivery address. On a location the structured parts are null when it has no structured address or that part is empty."
                    }
                }
            },
            "FulfillmentMode": {
                "type": "object",
                "properties": {
                    "enabled": {
                        "type": "boolean",
                        "description": "Online ordering in this mode is switched on for the location (off by default)."
                    },
                    "min_order_amount": {
                        "oneOf": [
                            {
                                "$ref": "#/components/schemas/Money"
                            },
                            {
                                "type": "null"
                            }
                        ],
                        "description": "Minimum order subtotal, the same for every mode; null — no minimum."
                    },
                    "fee": {
                        "oneOf": [
                            {
                                "$ref": "#/components/schemas/Money"
                            },
                            {
                                "type": "null"
                            }
                        ],
                        "description": "Delivery fee (flat, not taxed) — delivery only; null for pickup and dine-in."
                    }
                },
                "required": [
                    "enabled",
                    "min_order_amount",
                    "fee"
                ]
            },
            "Location": {
                "type": "object",
                "properties": {
                    "id": {
                        "$ref": "#/components/schemas/Id"
                    },
                    "name": {
                        "type": "string"
                    },
                    "phone": {
                        "type": [
                            "string",
                            "null"
                        ]
                    },
                    "address": {
                        "oneOf": [
                            {
                                "$ref": "#/components/schemas/Address"
                            },
                            {
                                "type": "null"
                            }
                        ],
                        "description": "Structured address when the location has one (`line1` = building + street, `line2` = unit; `country` is free text as entered, not an ISO code); `formatted` is always filled — the full address line, or the address laid out by the receipt template, or \"city, address\" for a location without a structured address (then the other fields are null). null — no address at all."
                    },
                    "timezone": {
                        "type": "string",
                        "example": "America/New_York",
                        "description": "IANA time zone of the location (its own when set and valid, else the account's). Hours, menu schedules and the stop list are in this local time."
                    },
                    "weekly_hours": {
                        "oneOf": [
                            {
                                "$ref": "#/components/schemas/WeeklyHours"
                            },
                            {
                                "type": "null"
                            }
                        ],
                        "description": "null — no working hours are set (an empty or zero-length interval is not taken to mean \"closed\" or \"24 hours\")."
                    },
                    "fulfillment": {
                        "type": "object",
                        "properties": {
                            "pickup": {
                                "$ref": "#/components/schemas/FulfillmentMode"
                            },
                            "delivery": {
                                "$ref": "#/components/schemas/FulfillmentMode"
                            },
                            "dine_in": {
                                "$ref": "#/components/schemas/FulfillmentMode"
                            }
                        },
                        "required": [
                            "pickup",
                            "delivery",
                            "dine_in"
                        ],
                        "description": "Online-ordering modes with the rules the server applies to online orders."
                    },
                    "currency": {
                        "type": "string",
                        "example": "USD",
                        "description": "ISO 4217 of the amounts above."
                    },
                    "money_step": {
                        "$ref": "#/components/schemas/Money",
                        "description": "Rounding step of this location's POS for line totals: \"0.01\", \"0.10\" or \"1.00\" (whole units — typical for KZT)."
                    },
                    "default_menu_id": {
                        "oneOf": [
                            {
                                "$ref": "#/components/schemas/Id"
                            },
                            {
                                "type": "null"
                            }
                        ],
                        "description": "The menu pinned to this location (see Menu); null when none or when it points at a deleted menu."
                    },
                    "updated_at": {
                        "type": "string",
                        "format": "date-time"
                    }
                },
                "required": [
                    "id",
                    "name",
                    "phone",
                    "address",
                    "timezone",
                    "weekly_hours",
                    "fulfillment",
                    "currency",
                    "money_step",
                    "default_menu_id",
                    "updated_at"
                ]
            },
            "Tax": {
                "type": "object",
                "properties": {
                    "id": {
                        "$ref": "#/components/schemas/Id"
                    },
                    "name": {
                        "type": "string"
                    },
                    "rate": {
                        "type": "string",
                        "example": "8.875",
                        "description": "Percent as the POS applies it (the stored value imported at four decimals). A negative rate marks \"no tax\": an item pointing at it carries no tax unless the default tax is added on top."
                    },
                    "included": {
                        "type": "boolean",
                        "description": "The row's own flag. It decides how the DEFAULT tax applies; an item's own tax is always treated as included in the price."
                    },
                    "kind": {
                        "type": "string",
                        "enum": [
                            "tax",
                            "fee"
                        ]
                    },
                    "is_default": {
                        "type": "boolean"
                    },
                    "deleted": {
                        "type": "boolean",
                        "description": "Kept in the list so that historical orders referring to it can be read."
                    }
                },
                "required": [
                    "id",
                    "name",
                    "rate",
                    "included",
                    "kind",
                    "is_default",
                    "deleted"
                ]
            },
            "Taxes": {
                "type": "object",
                "description": "Taxes as the PalomaPOS POS applies them. Every order line carries AT MOST ONE tax: the default tax when it is added on top with a positive rate (to every item); otherwise the item's own tax (Item.tax_id), always included in the price, unless its rate is negative; otherwise an included default tax; otherwise none. Item.effective_tax is this rule already applied — enough to estimate an order total exactly as the POS will book it. Per-item tax lists, per-location taxes and taxes on fees are not used by the POS and are not exposed.",
                "properties": {
                    "rounding": {
                        "type": "string",
                        "enum": [
                            "half_away_from_zero"
                        ],
                        "description": "Tax is rounded per line (never on the total), half away from zero."
                    },
                    "money_step": {
                        "$ref": "#/components/schemas/Money",
                        "description": "Account-level rounding step of line totals (\"0.01\", \"0.10\" or \"1.00\"); a location may differ — see Location.money_step."
                    },
                    "default_tax": {
                        "oneOf": [
                            {
                                "$ref": "#/components/schemas/DefaultTax"
                            },
                            {
                                "type": "null"
                            }
                        ],
                        "description": "null — no default tax, or it cannot be determined (see default_tax_ambiguous)."
                    },
                    "default_tax_ambiguous": {
                        "type": "boolean",
                        "description": "true — several default taxes share a name but differ in rate, so the POS choice is unpredictable; default_tax and every Item.effective_tax are then null. Fix the duplicate default taxes in the dashboard."
                    },
                    "taxes": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/Tax"
                        },
                        "description": "The whole tax and fee catalog, deleted rows included."
                    },
                    "rules": {
                        "type": "string",
                        "description": "The same rule in plain words."
                    }
                },
                "required": [
                    "rounding",
                    "money_step",
                    "default_tax",
                    "default_tax_ambiguous",
                    "taxes",
                    "rules"
                ]
            },
            "PaymentType": {
                "type": "object",
                "properties": {
                    "id": {
                        "$ref": "#/components/schemas/Id"
                    },
                    "name": {
                        "type": "string"
                    },
                    "kind": {
                        "type": "string",
                        "enum": [
                            "cash",
                            "card",
                            "other"
                        ],
                        "description": "cash / card — the type the locations use as their cash / card tender; other — neither, or the locations disagree."
                    },
                    "deleted": {
                        "type": "boolean",
                        "description": "Deleted types stay listed: orders in the history refer to them."
                    },
                    "updated_at": {
                        "type": "string",
                        "format": "date-time"
                    }
                },
                "required": [
                    "id",
                    "name",
                    "kind",
                    "deleted",
                    "updated_at"
                ]
            },
            "Category": {
                "type": "object",
                "properties": {
                    "id": {
                        "$ref": "#/components/schemas/Id"
                    },
                    "name": {
                        "type": "string"
                    },
                    "parent_id": {
                        "oneOf": [
                            {
                                "$ref": "#/components/schemas/Id"
                            },
                            {
                                "type": "null"
                            }
                        ],
                        "description": "Parent category; null — top level. It may point at a category that is not listed (hidden from the POS menu)."
                    },
                    "sort_index": {
                        "type": "integer"
                    },
                    "deleted": {
                        "type": "boolean",
                        "const": false
                    },
                    "updated_at": {
                        "type": "string",
                        "format": "date-time"
                    }
                },
                "required": [
                    "id",
                    "name",
                    "parent_id",
                    "sort_index",
                    "deleted",
                    "updated_at"
                ]
            },
            "Item": {
                "type": "object",
                "properties": {
                    "id": {
                        "$ref": "#/components/schemas/Id"
                    },
                    "name": {
                        "type": "string"
                    },
                    "description": {
                        "type": [
                            "string",
                            "null"
                        ]
                    },
                    "price": {
                        "oneOf": [
                            {
                                "$ref": "#/components/schemas/Money"
                            },
                            {
                                "type": "null"
                            }
                        ],
                        "description": "Unit price exactly as the POS rings it (for a weighted item — per kilogram). null when open_price."
                    },
                    "open_price": {
                        "type": "boolean",
                        "description": "The cashier types the price at the POS; such an item cannot be priced in advance."
                    },
                    "currency": {
                        "type": "string",
                        "example": "USD"
                    },
                    "category_id": {
                        "oneOf": [
                            {
                                "$ref": "#/components/schemas/Id"
                            },
                            {
                                "type": "null"
                            }
                        ],
                        "description": "May point at a category hidden from the POS menu (not in /categories)."
                    },
                    "sort_index": {
                        "type": "integer"
                    },
                    "image_url": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "format": "uri"
                    },
                    "barcodes": {
                        "type": "array",
                        "items": {
                            "type": "string"
                        },
                        "description": "Main barcode first."
                    },
                    "sku": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "Article number (артикул)."
                    },
                    "plu": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "Scale PLU code of a weighted item."
                    },
                    "unit": {
                        "type": "string",
                        "enum": [
                            "each",
                            "weight"
                        ],
                        "description": "weight — sold by weight in kilograms; quantity may be fractional."
                    },
                    "tax_id": {
                        "oneOf": [
                            {
                                "$ref": "#/components/schemas/Id"
                            },
                            {
                                "type": "null"
                            }
                        ],
                        "description": "The item's own tax row (may point at a deleted or missing row); null — none. Use effective_tax to price the item."
                    },
                    "effective_tax": {
                        "oneOf": [
                            {
                                "$ref": "#/components/schemas/EffectiveTax"
                            },
                            {
                                "type": "null"
                            }
                        ],
                        "description": "The tax the POS applies to this item under the rule of GET /v1/taxes; null — untaxed (or the default tax is ambiguous, see Taxes.default_tax_ambiguous)."
                    },
                    "modifier_group_ids": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/Id"
                        },
                        "description": "Modifier groups the POS offers for this item, in order: the item's own; when it has none — its category's."
                    },
                    "available_for": {
                        "type": "object",
                        "properties": {
                            "pickup": {
                                "type": "boolean"
                            },
                            "delivery": {
                                "type": "boolean"
                            }
                        },
                        "required": [
                            "pickup",
                            "delivery"
                        ]
                    },
                    "deleted": {
                        "type": "boolean",
                        "const": false
                    },
                    "updated_at": {
                        "type": "string",
                        "format": "date-time",
                        "description": "Last edit of the item row itself."
                    }
                },
                "required": [
                    "id",
                    "name",
                    "description",
                    "price",
                    "open_price",
                    "currency",
                    "category_id",
                    "sort_index",
                    "image_url",
                    "barcodes",
                    "sku",
                    "plu",
                    "unit",
                    "tax_id",
                    "effective_tax",
                    "modifier_group_ids",
                    "available_for",
                    "deleted",
                    "updated_at"
                ]
            },
            "Modifier": {
                "type": "object",
                "properties": {
                    "id": {
                        "$ref": "#/components/schemas/Id"
                    },
                    "item_id": {
                        "oneOf": [
                            {
                                "$ref": "#/components/schemas/Id"
                            },
                            {
                                "type": "null"
                            }
                        ],
                        "description": "Linked catalog item of the modifier, if any."
                    },
                    "name": {
                        "type": "string"
                    },
                    "price": {
                        "$ref": "#/components/schemas/Money",
                        "description": "Charged per unit of the modifier, already including the group's own surcharge — exactly what the POS adds to the line."
                    },
                    "is_default": {
                        "type": "boolean"
                    },
                    "max_quantity": {
                        "type": [
                            "integer",
                            "null"
                        ],
                        "description": "Per-modifier limit; null — only the group limit applies."
                    },
                    "sort_index": {
                        "type": "integer"
                    }
                },
                "required": [
                    "id",
                    "item_id",
                    "name",
                    "price",
                    "is_default",
                    "max_quantity",
                    "sort_index"
                ]
            },
            "ModifierGroup": {
                "type": "object",
                "properties": {
                    "id": {
                        "$ref": "#/components/schemas/Id"
                    },
                    "name": {
                        "type": "string"
                    },
                    "min_selected": {
                        "type": "integer",
                        "description": "Units the guest must pick (0 — optional)."
                    },
                    "max_selected": {
                        "type": [
                            "integer",
                            "null"
                        ],
                        "description": "Most units in the group; null — no limit."
                    },
                    "currency": {
                        "type": "string",
                        "example": "USD"
                    },
                    "modifiers": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/Modifier"
                        },
                        "description": "In POS order."
                    },
                    "deleted": {
                        "type": "boolean",
                        "const": false
                    },
                    "updated_at": {
                        "type": "string",
                        "format": "date-time"
                    }
                },
                "required": [
                    "id",
                    "name",
                    "min_selected",
                    "max_selected",
                    "currency",
                    "modifiers",
                    "deleted",
                    "updated_at"
                ]
            },
            "MenuEntry": {
                "type": "object",
                "properties": {
                    "id": {
                        "$ref": "#/components/schemas/Id"
                    },
                    "parent_id": {
                        "oneOf": [
                            {
                                "$ref": "#/components/schemas/Id"
                            },
                            {
                                "type": "null"
                            }
                        ],
                        "description": "Folder of the menu this entry sits in; null — top level."
                    },
                    "is_folder": {
                        "type": "boolean"
                    },
                    "item_id": {
                        "oneOf": [
                            {
                                "$ref": "#/components/schemas/Id"
                            },
                            {
                                "type": "null"
                            }
                        ],
                        "description": "The catalog item; null for a folder."
                    },
                    "name": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "The entry's own name; null — use the item's name."
                    },
                    "price": {
                        "oneOf": [
                            {
                                "$ref": "#/components/schemas/Money"
                            },
                            {
                                "type": "null"
                            }
                        ],
                        "description": "The menu price of the item; null — the item's own price applies (or a folder, or open_price)."
                    },
                    "open_price": {
                        "type": "boolean",
                        "description": "In this menu the cashier types the price."
                    },
                    "sort_index": {
                        "type": "integer",
                        "description": "Entries come ordered by (sort_index, id)."
                    }
                },
                "required": [
                    "id",
                    "parent_id",
                    "is_folder",
                    "item_id",
                    "name",
                    "price",
                    "open_price",
                    "sort_index"
                ]
            },
            "Menu": {
                "type": "object",
                "description": "A back-office menu: a curated view of the catalog with its own prices. The POS offers at a location every menu that applies there; a menu pinned to the location (default_for_location_ids) wins while its own schedule is open.",
                "properties": {
                    "id": {
                        "$ref": "#/components/schemas/Id"
                    },
                    "name": {
                        "type": "string"
                    },
                    "currency": {
                        "type": "string",
                        "example": "USD"
                    },
                    "location_ids": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/Id"
                        },
                        "description": "Where the menu can apply: pinned locations plus the locations of its windows; for a menu without a schedule — every location."
                    },
                    "default_for_location_ids": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/Id"
                        },
                        "description": "Locations that pin this menu (Location.default_menu_id)."
                    },
                    "schedule": {
                        "oneOf": [
                            {
                                "type": "object",
                                "properties": {
                                    "windows": {
                                        "type": "array",
                                        "items": {
                                            "$ref": "#/components/schemas/MenuWindow"
                                        }
                                    }
                                },
                                "required": [
                                    "windows"
                                ]
                            },
                            {
                                "type": "null"
                            }
                        ],
                        "description": "null — always on. An empty `windows` list — scheduled only on deleted rules: never offered."
                    },
                    "entries": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/MenuEntry"
                        }
                    },
                    "deleted": {
                        "type": "boolean",
                        "const": false
                    },
                    "updated_at": {
                        "type": "string",
                        "format": "date-time"
                    }
                },
                "required": [
                    "id",
                    "name",
                    "currency",
                    "location_ids",
                    "default_for_location_ids",
                    "schedule",
                    "entries",
                    "deleted",
                    "updated_at"
                ]
            },
            "StopListEntry": {
                "type": "object",
                "properties": {
                    "item_id": {
                        "$ref": "#/components/schemas/Id"
                    },
                    "until": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "format": "date-time",
                        "description": "null — until put back on sale."
                    },
                    "source": {
                        "type": "string",
                        "enum": [
                            "manual",
                            "stock"
                        ],
                        "description": "stock — the counted stock ran out (recorded by the POS); manual — stopped without a count."
                    }
                },
                "required": [
                    "item_id",
                    "until",
                    "source"
                ]
            },
            "OrderLineInput": {
                "type": "object",
                "properties": {
                    "item_id": {
                        "$ref": "#/components/schemas/Id"
                    },
                    "quantity": {
                        "type": "string",
                        "pattern": "^\\d{1,4}(\\.\\d{1,3})?$",
                        "example": "1",
                        "description": "Decimal > 0, up to 3 places; fractions only for items sold by weight (kg). A JSON integer is accepted too."
                    },
                    "modifiers": {
                        "type": "array",
                        "items": {
                            "type": "object",
                            "properties": {
                                "modifier_id": {
                                    "$ref": "#/components/schemas/Id"
                                },
                                "quantity": {
                                    "type": "integer",
                                    "minimum": 1,
                                    "default": 1,
                                    "maximum": 1,
                                    "description": "Only 1 for now: the POS books a modifier of an app order once per line (it does not read an option quantity yet), so 2 or more would be charged by the API but not by the cashier — 400 invalid_request, details.fields `lines[i].modifiers[j].quantity: must_be_1`. Values up to 99 are reserved for when the POS reads it."
                                }
                            },
                            "required": [
                                "modifier_id"
                            ]
                        },
                        "maxItems": 50,
                        "description": "Options of the item's modifier groups (ModifierGroup.modifiers[].id; the item's own groups, or its category's when it has none), each at most once and (for now) with quantity 1. Per group the number of options is min_selected…max_selected (0 = no limit)."
                    },
                    "note": {
                        "type": "string",
                        "maxLength": 200
                    }
                },
                "required": [
                    "item_id",
                    "quantity"
                ]
            },
            "OrderInput": {
                "type": "object",
                "properties": {
                    "location_id": {
                        "allOf": [
                            {
                                "$ref": "#/components/schemas/Id"
                            }
                        ],
                        "description": "Location (GET /locations)."
                    },
                    "fulfillment": {
                        "type": "object",
                        "properties": {
                            "type": {
                                "type": "string",
                                "enum": [
                                    "pickup",
                                    "delivery"
                                ]
                            },
                            "asap": {
                                "type": "boolean"
                            },
                            "ready_at": {
                                "type": "string",
                                "format": "date-time",
                                "description": "RFC 3339 with offset. Stored as the POS 'ready by' time."
                            }
                        },
                        "required": [
                            "type"
                        ],
                        "description": "Exactly one of `asap: true` and `ready_at` (not in the past, at most 7 days ahead). The mode must be switched on for the location (online.order.pickup / delivery)."
                    },
                    "customer": {
                        "type": "object",
                        "properties": {
                            "name": {
                                "type": "string",
                                "maxLength": 100
                            },
                            "phone": {
                                "type": "string",
                                "example": "+13055550100",
                                "description": "E.164",
                                "pattern": "^\\+[1-9]\\d{6,14}$"
                            }
                        },
                        "description": "Optional. The guest is matched to an existing customer by phone (E.164 and the local forms the POS stores), otherwise created."
                    },
                    "delivery_address": {
                        "allOf": [
                            {
                                "$ref": "#/components/schemas/Address"
                            }
                        ],
                        "description": "Required for delivery (formatted or line1; parts are joined into one line of at most 250 characters, otherwise 400 invalid_request `delivery_address: too_long`). Ignored for pickup; not required by /orders/quote."
                    },
                    "note": {
                        "type": "string",
                        "maxLength": 200
                    },
                    "lines": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/OrderLineInput"
                        },
                        "minItems": 1,
                        "maxItems": 100,
                        "description": "At most 100 lines and at most 500 check rows counting every modifier as a row (otherwise 400 invalid_request, details.fields `lines: at_most_500_rows_including_modifiers`)."
                    },
                    "tip": {
                        "type": "object",
                        "properties": {
                            "amount": {
                                "$ref": "#/components/schemas/Money"
                            }
                        },
                        "description": "Not taxed, never part of `total`; at most the subtotal."
                    },
                    "external_id": {
                        "type": "string",
                        "maxLength": 50,
                        "description": "The app's own id for the order (d_order_delivery.foreign_order_id, at most 50 characters); shown back as source.external_id."
                    },
                    "expected_total": {
                        "allOf": [
                            {
                                "$ref": "#/components/schemas/Money"
                            }
                        ],
                        "description": "The total already told to the guest (without the tip). The server prices the cart with the POS formula; if the total differs the call fails with 409 total_mismatch (details: expected, actual, quote) and nothing is created; if the cart cannot be priced — 422 quote_unsupported. Ignored by /orders/quote."
                    }
                },
                "required": [
                    "location_id",
                    "fulfillment",
                    "lines"
                ],
                "description": "Cart of an order or a quote. Prices, taxes, the order number and the source are set by PalomaPOS, never taken from the body. Unknown fields are ignored. Texts are stored without characters outside the Basic Multilingual Plane (emoji) and control characters."
            },
            "TaxLine": {
                "type": "object",
                "properties": {
                    "tax_id": {
                        "oneOf": [
                            {
                                "$ref": "#/components/schemas/Id"
                            },
                            {
                                "type": "null"
                            }
                        ]
                    },
                    "name": {
                        "type": "string"
                    },
                    "amount": {
                        "$ref": "#/components/schemas/Money"
                    },
                    "included": {
                        "type": "boolean",
                        "description": "true — VAT already inside the prices (informational, does not add to the total); false — added on top. Absent on fees."
                    },
                    "rate": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "example": "8.875",
                        "description": "Percent as a decimal string, when known."
                    }
                },
                "required": [
                    "tax_id",
                    "name",
                    "amount"
                ]
            },
            "QuoteLine": {
                "type": "object",
                "properties": {
                    "item_id": {
                        "$ref": "#/components/schemas/Id"
                    },
                    "name": {
                        "type": "string"
                    },
                    "quantity": {
                        "type": "string"
                    },
                    "unit_price": {
                        "allOf": [
                            {
                                "$ref": "#/components/schemas/Money"
                            }
                        ],
                        "description": "What the cashier would ring at this location now: the location's pinned menu price or the catalog price."
                    },
                    "modifiers": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/QuoteLineModifier"
                        }
                    },
                    "modifiers_total": {
                        "allOf": [
                            {
                                "$ref": "#/components/schemas/Money"
                            }
                        ],
                        "description": "Σ modifiers[].total."
                    },
                    "subtotal": {
                        "allOf": [
                            {
                                "$ref": "#/components/schemas/Money"
                            }
                        ],
                        "description": "Line amount the tax is computed on: (unit_price + Σ option prices) × quantity, rounded once like the POS (to whole units on accounts without cents)."
                    },
                    "taxes": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/TaxLine"
                        },
                        "description": "0 or 1 entry: the POS puts at most one tax on a line."
                    },
                    "note": {
                        "type": [
                            "string",
                            "null"
                        ]
                    }
                },
                "required": [
                    "item_id",
                    "name",
                    "quantity",
                    "unit_price",
                    "modifiers",
                    "modifiers_total",
                    "subtotal",
                    "taxes",
                    "note"
                ]
            },
            "Quote": {
                "type": "object",
                "description": "The cart priced exactly as the PalomaPOS POS v2 would book it (the POS formula ported to the server and pinned by golden cases generated by the POS itself): taxes per line, rounded per line, half away from zero. The delivery fee is the location's flat fee, untaxed. The tip is outside `total`.",
                "properties": {
                    "currency": {
                        "type": "string",
                        "example": "USD"
                    },
                    "lines": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/QuoteLine"
                        }
                    },
                    "subtotal": {
                        "$ref": "#/components/schemas/Money"
                    },
                    "tax_total": {
                        "allOf": [
                            {
                                "$ref": "#/components/schemas/Money"
                            }
                        ],
                        "description": "Added tax plus VAT included in prices (informational when taxes_included_in_prices)."
                    },
                    "taxes": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/OrderTax"
                        }
                    },
                    "fees": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/TaxLine"
                        },
                        "description": "Always empty: carts the POS would add automatic fees to are refused (quote_unsupported)."
                    },
                    "taxes_included_in_prices": {
                        "type": "boolean"
                    },
                    "delivery_fee": {
                        "$ref": "#/components/schemas/Money"
                    },
                    "tip": {
                        "$ref": "#/components/schemas/Money"
                    },
                    "total": {
                        "allOf": [
                            {
                                "$ref": "#/components/schemas/Money"
                            }
                        ],
                        "description": "What the guest pays without the tip: subtotal + added tax + delivery fee. A payment (POST /orders/{id}/payments) must equal it."
                    },
                    "total_with_tip": {
                        "$ref": "#/components/schemas/Money"
                    }
                },
                "required": [
                    "currency",
                    "lines",
                    "subtotal",
                    "tax_total",
                    "taxes",
                    "fees",
                    "taxes_included_in_prices",
                    "delivery_fee",
                    "tip",
                    "total",
                    "total_with_tip"
                ],
                "example": {
                    "currency": "USD",
                    "lines": [
                        {
                            "item_id": "501",
                            "name": "Cheeseburger",
                            "quantity": "2",
                            "unit_price": "12.50",
                            "modifiers": [
                                {
                                    "modifier_id": "901",
                                    "name": "Extra cheese",
                                    "quantity": "2",
                                    "unit_price": "1.25",
                                    "total": "2.50"
                                }
                            ],
                            "modifiers_total": "2.50",
                            "subtotal": "27.50",
                            "taxes": [
                                {
                                    "tax_id": "1",
                                    "name": "Sales Tax",
                                    "amount": "2.44",
                                    "included": false,
                                    "rate": "8.875"
                                }
                            ],
                            "note": "No onions"
                        }
                    ],
                    "subtotal": "27.50",
                    "tax_total": "2.44",
                    "taxes": [
                        {
                            "tax_id": "1",
                            "name": "Sales Tax",
                            "amount": "2.44",
                            "included": false
                        }
                    ],
                    "fees": [],
                    "taxes_included_in_prices": false,
                    "delivery_fee": "5.00",
                    "tip": "3.00",
                    "total": "34.94",
                    "total_with_tip": "37.94"
                }
            },
            "OrderPayment": {
                "type": "object",
                "description": "A payment row of the order. Card numbers, expiry, holder and terminal data are never returned.",
                "properties": {
                    "id": {
                        "oneOf": [
                            {
                                "$ref": "#/components/schemas/Id"
                            },
                            {
                                "type": "null"
                            }
                        ],
                        "description": "null only for a legacy order paid with one payment type and no payment rows (d_order.paymentid)."
                    },
                    "payment_type_id": {
                        "oneOf": [
                            {
                                "$ref": "#/components/schemas/Id"
                            },
                            {
                                "type": "null"
                            }
                        ]
                    },
                    "amount": {
                        "allOf": [
                            {
                                "$ref": "#/components/schemas/Money"
                            }
                        ],
                        "description": "Signed as stored: refunds and voids are negative, so Σ amount is the net collected."
                    },
                    "tip_amount": {
                        "allOf": [
                            {
                                "$ref": "#/components/schemas/Money"
                            }
                        ],
                        "description": "Signed like amount."
                    },
                    "kind": {
                        "type": "string",
                        "enum": [
                            "sale",
                            "refund",
                            "void"
                        ]
                    },
                    "reference": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "Provider payment id (e.g. a Stripe PaymentIntent) when recorded through POST /orders/{id}/payments or by an integration."
                    },
                    "created_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "format": "date-time"
                    }
                },
                "required": [
                    "id",
                    "payment_type_id",
                    "amount",
                    "tip_amount",
                    "kind",
                    "reference",
                    "created_at"
                ]
            },
            "Order": {
                "type": "object",
                "description": "An order of any source (POS, online ordering, aggregators, apps). Money in the account currency; times in the time zone of the order's location (s_automated_point.timezone), or the account's when the location has none — the POS stores order times as its local wall clock.",
                "properties": {
                    "id": {
                        "$ref": "#/components/schemas/Id"
                    },
                    "number": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "example": "42",
                        "description": "What the cashier sees (the POS order number, d_order.idout) and what to tell the guest."
                    },
                    "location_id": {
                        "oneOf": [
                            {
                                "$ref": "#/components/schemas/Id"
                            },
                            {
                                "type": "null"
                            }
                        ]
                    },
                    "deleted": {
                        "type": "boolean",
                        "description": "Deleted orders come only in `since` passes (and by id)."
                    },
                    "source": {
                        "type": "object",
                        "properties": {
                            "app_client_id": {
                                "type": [
                                    "string",
                                    "null"
                                ],
                                "description": "client_id of the app that created the order through this API; null for other sources."
                            },
                            "name": {
                                "type": [
                                    "string",
                                    "null"
                                ],
                                "description": "Source name as the POS shows it (d_order_delivery.source_name: the app's display name, 'online', 'halyk', …); null for orders rung on the POS."
                            },
                            "external_id": {
                                "type": [
                                    "string",
                                    "null"
                                ],
                                "description": "The source's own order id (external_id of POST /orders)."
                            }
                        },
                        "required": [
                            "app_client_id",
                            "name",
                            "external_id"
                        ]
                    },
                    "status": {
                        "type": "string",
                        "enum": [
                            "new",
                            "accepted",
                            "in_progress",
                            "ready",
                            "out_for_delivery",
                            "cancelled",
                            "picked_up",
                            "delivered",
                            "completed"
                        ],
                        "description": "Orders with a pickup/delivery row follow the POS delivery status (d_order_delivery.status_id 0,1 new · 2 accepted · 3 in_progress · 4 ready · 5 out_for_delivery · 6 cancelled · 7 picked_up · 8 delivered). Orders without one (dine-in, counter): completed once the POS closed the check, otherwise in_progress."
                    },
                    "fulfillment": {
                        "type": "object",
                        "properties": {
                            "type": {
                                "type": "string",
                                "enum": [
                                    "pickup",
                                    "delivery",
                                    "dine_in",
                                    "counter"
                                ]
                            },
                            "asap": {
                                "type": [
                                    "boolean",
                                    "null"
                                ],
                                "description": "null for dine-in / counter orders."
                            },
                            "ready_at": {
                                "type": [
                                    "string",
                                    "null"
                                ],
                                "format": "date-time"
                            }
                        },
                        "required": [
                            "type",
                            "asap",
                            "ready_at"
                        ]
                    },
                    "customer": {
                        "type": "object",
                        "properties": {
                            "id": {
                                "oneOf": [
                                    {
                                        "$ref": "#/components/schemas/Id"
                                    },
                                    {
                                        "type": "null"
                                    }
                                ]
                            },
                            "name": {
                                "type": [
                                    "string",
                                    "null"
                                ]
                            },
                            "phone": {
                                "type": [
                                    "string",
                                    "null"
                                ]
                            }
                        },
                        "required": [
                            "id",
                            "name",
                            "phone"
                        ],
                        "description": "With customers:read — the POS customer the order is attached to (id, name, phone). On an order created by the calling app, without customers:read — only what the app sent: phone (E.164), with id and name null (the order is attached to a POS customer by phone; returning that customer would tell whose number it is). On other orders without customers:read — id only."
                    },
                    "delivery_address": {
                        "oneOf": [
                            {
                                "$ref": "#/components/schemas/Address"
                            },
                            {
                                "type": "null"
                            }
                        ],
                        "description": "Only `formatted` (the POS stores one line). Returned with customers:read, or on an order created by the calling app; otherwise null."
                    },
                    "note": {
                        "type": [
                            "string",
                            "null"
                        ]
                    },
                    "lines": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/OrderLine"
                        }
                    },
                    "currency": {
                        "type": "string",
                        "example": "USD"
                    },
                    "subtotal": {
                        "allOf": [
                            {
                                "$ref": "#/components/schemas/Money"
                            }
                        ],
                        "description": "Σ line subtotals (d_order.subtotal)."
                    },
                    "discount_total": {
                        "$ref": "#/components/schemas/Money"
                    },
                    "service_charge": {
                        "allOf": [
                            {
                                "$ref": "#/components/schemas/Money"
                            }
                        ],
                        "description": "Automatic service charge (auto-gratuity) booked by the POS."
                    },
                    "tax_total": {
                        "allOf": [
                            {
                                "$ref": "#/components/schemas/Money"
                            }
                        ],
                        "description": "Σ taxes, included VAT counted too (informational for VAT)."
                    },
                    "taxes": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/OrderTax"
                        }
                    },
                    "fees": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/TaxLine"
                        },
                        "description": "Order-level fee rows (older integrations)."
                    },
                    "taxes_included_in_prices": {
                        "type": "boolean"
                    },
                    "delivery_fee": {
                        "$ref": "#/components/schemas/Money"
                    },
                    "tip": {
                        "allOf": [
                            {
                                "$ref": "#/components/schemas/Money"
                            }
                        ],
                        "description": "From the payment rows when they carry tips, otherwise the tip declared with the order."
                    },
                    "total": {
                        "allOf": [
                            {
                                "$ref": "#/components/schemas/Money"
                            }
                        ],
                        "description": "What the order costs without the tip (d_order.totalsum): lines − discounts + added tax + service + delivery fee for orders created through this API. For revenue figures use `GET /reports/sales-daily` (it matches the back-office sales report): summing order totals differs from it because refunds are separate documents, orders are counted by the day they were closed, and the tip is not in `total`."
                    },
                    "paid": {
                        "type": "boolean",
                        "description": "Σ payments[].amount covers total. An order with a zero total (a 100% discount) is paid once the POS has closed the check."
                    },
                    "payments": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/OrderPayment"
                        }
                    },
                    "cancel_reason": {
                        "type": [
                            "string",
                            "null"
                        ]
                    },
                    "created_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "format": "date-time"
                    },
                    "updated_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "format": "date-time",
                        "description": "The latest change among the order header, its delivery row, payments, discounts and taxes — the rows `since` tracks."
                    },
                    "closed_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "format": "date-time"
                    }
                },
                "required": [
                    "id",
                    "number",
                    "location_id",
                    "deleted",
                    "source",
                    "status",
                    "fulfillment",
                    "customer",
                    "delivery_address",
                    "note",
                    "lines",
                    "currency",
                    "subtotal",
                    "discount_total",
                    "service_charge",
                    "tax_total",
                    "taxes",
                    "fees",
                    "taxes_included_in_prices",
                    "delivery_fee",
                    "tip",
                    "total",
                    "paid",
                    "payments",
                    "cancel_reason",
                    "created_at",
                    "updated_at",
                    "closed_at"
                ],
                "example": {
                    "id": "10432",
                    "number": "42",
                    "location_id": "3",
                    "deleted": false,
                    "source": {
                        "app_client_id": "ppc_0123456789abcdef0123456789abcdef",
                        "name": "Example Orders App",
                        "external_id": "ord-8812"
                    },
                    "status": "new",
                    "fulfillment": {
                        "type": "pickup",
                        "asap": false,
                        "ready_at": "2026-09-29T18:30:00-04:00"
                    },
                    "customer": {
                        "id": null,
                        "name": null,
                        "phone": "+13055550100"
                    },
                    "delivery_address": null,
                    "note": "Ring the bell",
                    "lines": [
                        {
                            "id": "90001",
                            "item_id": "501",
                            "name": "Cheeseburger",
                            "quantity": "2",
                            "unit_price": "12.50",
                            "modifiers": [
                                {
                                    "id": "90002",
                                    "modifier_id": "901",
                                    "name": "Extra cheese",
                                    "quantity": "2",
                                    "unit_price": "1.25",
                                    "total": "2.50"
                                }
                            ],
                            "modifiers_total": "2.50",
                            "subtotal": "27.50",
                            "discount_total": "0.00",
                            "taxes": [
                                {
                                    "tax_id": "1",
                                    "name": "Sales Tax",
                                    "amount": "2.44",
                                    "included": false,
                                    "rate": "8.875"
                                }
                            ],
                            "note": "No onions"
                        }
                    ],
                    "currency": "USD",
                    "subtotal": "27.50",
                    "discount_total": "0.00",
                    "service_charge": "0.00",
                    "tax_total": "2.44",
                    "taxes": [
                        {
                            "tax_id": "1",
                            "name": "Sales Tax",
                            "amount": "2.44",
                            "included": false
                        }
                    ],
                    "fees": [],
                    "taxes_included_in_prices": false,
                    "delivery_fee": "0.00",
                    "tip": "3.00",
                    "total": "29.94",
                    "paid": false,
                    "payments": [],
                    "cancel_reason": null,
                    "created_at": "2026-09-29T17:52:10-04:00",
                    "updated_at": "2026-09-29T17:52:10-04:00",
                    "closed_at": null
                }
            },
            "PaymentInput": {
                "type": "object",
                "properties": {
                    "amount": {
                        "allOf": [
                            {
                                "$ref": "#/components/schemas/Money"
                            }
                        ],
                        "description": "Must equal the amount due: the order total (without tip) minus what is already recorded. Otherwise 409 total_mismatch with details.expected (the amount due) and details.actual."
                    },
                    "tip_amount": {
                        "allOf": [
                            {
                                "$ref": "#/components/schemas/Money"
                            }
                        ],
                        "description": "Optional, at most amount; recorded on the payment row, outside the order total, and becomes the order's tip. Omitted — the order keeps the tip it was created with and the payment row has none."
                    },
                    "provider": {
                        "type": "string",
                        "maxLength": 64,
                        "example": "stripe",
                        "description": "Who took the money."
                    },
                    "reference": {
                        "type": "string",
                        "maxLength": 128,
                        "pattern": "^[\\x21-\\x7E]+$",
                        "description": "Provider payment id (e.g. a Stripe PaymentIntent id). Recording the same reference again returns the existing payment."
                    }
                },
                "required": [
                    "amount",
                    "provider",
                    "reference"
                ]
            },
            "CancelInput": {
                "type": "object",
                "properties": {
                    "reason": {
                        "type": "string",
                        "maxLength": 200,
                        "description": "Shown to the cashier (d_order_delivery.cancel_reason)."
                    }
                },
                "required": [
                    "reason"
                ]
            },
            "Customer": {
                "type": "object",
                "description": "A customer of the business (`s_clients`). Customer = not a folder, not deleted and not a pure supplier — the rule of the back-office buyers list. Only these personal fields are exposed; tax ids, bank details, loyalty card numbers, addresses and notes never are. A tombstone (`deleted: true`, `since` passes only) carries `id` and `updated_at`; its personal fields are null.",
                "properties": {
                    "id": {
                        "$ref": "#/components/schemas/Id"
                    },
                    "name": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "Display name (`name`, else `fullname`)."
                    },
                    "phone": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "As entered in the POS or back office; not normalized."
                    },
                    "email": {
                        "type": [
                            "string",
                            "null"
                        ]
                    },
                    "birthday": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "format": "date"
                    },
                    "deleted": {
                        "type": "boolean",
                        "description": "true — the record was deleted or is no longer a customer (moved to suppliers). Only in `since` passes."
                    },
                    "updated_at": {
                        "type": "string",
                        "format": "date-time",
                        "description": "When this record last changed (for a tombstone — when it was deleted)."
                    }
                },
                "required": [
                    "id",
                    "name",
                    "phone",
                    "email",
                    "birthday",
                    "deleted",
                    "updated_at"
                ]
            },
            "Employee": {
                "type": "object",
                "description": "An employee. Never exposed: passwords, PIN, session keys, push tokens, messenger ids, phone and email. A tombstone (`deleted: true`, `since` passes only) carries `id` and `updated_at`.",
                "properties": {
                    "id": {
                        "$ref": "#/components/schemas/Id"
                    },
                    "name": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "Full name, else the back-office login (how the dashboard and the POS show the employee). null only for a tombstone."
                    },
                    "position": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "Job position name, null when not set."
                    },
                    "location_ids": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/Id"
                        },
                        "description": "Locations of the POS workplaces the employee may sign in at."
                    },
                    "active": {
                        "type": "boolean",
                        "description": "The employee may sign in (a login-enabled operator). A dismissed employee comes as `deleted: true` instead."
                    },
                    "deleted": {
                        "type": "boolean"
                    },
                    "updated_at": {
                        "type": "string",
                        "format": "date-time",
                        "description": "When the employee or their workplaces last changed."
                    }
                },
                "required": [
                    "id",
                    "name",
                    "position",
                    "location_ids",
                    "active",
                    "deleted",
                    "updated_at"
                ]
            },
            "Shift": {
                "type": "object",
                "description": "A POS shift (`d_changes`). Times are the location's wall clock, sent with the location's UTC offset. Who closed the shift and shift totals are not recorded by the POS, so they are not part of the object — sales of a period come from `/reports/sales-daily`.",
                "properties": {
                    "id": {
                        "$ref": "#/components/schemas/Id"
                    },
                    "location_id": {
                        "oneOf": [
                            {
                                "$ref": "#/components/schemas/Id"
                            },
                            {
                                "type": "null"
                            }
                        ],
                        "description": "null for legacy rows without a location."
                    },
                    "opened_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "format": "date-time"
                    },
                    "closed_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "format": "date-time",
                        "description": "null while the shift is open."
                    },
                    "closed": {
                        "type": "boolean"
                    },
                    "opened_by_employee_id": {
                        "oneOf": [
                            {
                                "$ref": "#/components/schemas/Id"
                            },
                            {
                                "type": "null"
                            }
                        ],
                        "description": "Employee who opened the shift."
                    },
                    "updated_at": {
                        "type": "string",
                        "format": "date-time"
                    }
                },
                "required": [
                    "id",
                    "location_id",
                    "opened_at",
                    "closed_at",
                    "closed",
                    "opened_by_employee_id",
                    "updated_at"
                ]
            },
            "SalesDay": {
                "type": "object",
                "description": "Sales of one location on one calendar day. Counts closed, non-deleted orders by the day they were closed (the location's own clock), like the back-office «Sales act» report: every order line except the components of a combo (their price is in the combo line); modifiers count as their own lines. Voided items, items moved to another check and refund documents are lines with a negative quantity and are netted in — all amounts are after voids, transfers and refunds. Money is exact: every line is rounded to cents half away from zero, then summed as integers, so the item `gross` values add up to the day's `gross` exactly.",
                "properties": {
                    "date": {
                        "type": "string",
                        "format": "date"
                    },
                    "location_id": {
                        "oneOf": [
                            {
                                "$ref": "#/components/schemas/Id"
                            },
                            {
                                "type": "null"
                            }
                        ],
                        "description": "null for legacy orders without a location."
                    },
                    "orders": {
                        "type": "integer",
                        "description": "Closed sale orders (refund documents are not counted, their lines reduce the amounts)."
                    },
                    "gross": {
                        "allOf": [
                            {
                                "$ref": "#/components/schemas/Money"
                            }
                        ],
                        "description": "Price × quantity of the lines, before discounts and service charges. A tax included in the price is inside; a tax added on top is not."
                    },
                    "discounts": {
                        "allOf": [
                            {
                                "$ref": "#/components/schemas/Money"
                            }
                        ],
                        "description": "Discounts of the lines (order-level discounts are spread over the lines by the POS)."
                    },
                    "service_charges": {
                        "allOf": [
                            {
                                "$ref": "#/components/schemas/Money"
                            }
                        ],
                        "description": "Service charges (service percent / auto-gratuity) of the lines."
                    },
                    "net": {
                        "allOf": [
                            {
                                "$ref": "#/components/schemas/Money"
                            }
                        ],
                        "description": "gross − discounts. net + service_charges is the «Total» of the back-office sales act."
                    },
                    "tax": {
                        "allOf": [
                            {
                                "$ref": "#/components/schemas/Money"
                            }
                        ],
                        "description": "Taxes recorded on the day's orders, both added on top and included in prices. Registers that do not record tax lines (the CIS Windows POS) show 0."
                    },
                    "tax_included": {
                        "allOf": [
                            {
                                "$ref": "#/components/schemas/Money"
                            }
                        ],
                        "description": "The part of `tax` that is already inside the prices (VAT-style); the rest was added on top."
                    },
                    "items": {
                        "type": "array",
                        "description": "Per item, sorted by gross descending. Items whose quantity and gross both net out to zero are omitted.",
                        "items": {
                            "type": "object",
                            "properties": {
                                "item_id": {
                                    "oneOf": [
                                        {
                                            "$ref": "#/components/schemas/Id"
                                        },
                                        {
                                            "type": "null"
                                        }
                                    ],
                                    "description": "null for lines without a catalog item."
                                },
                                "name": {
                                    "type": "string",
                                    "description": "Current catalog name; for an item deleted from the catalog — the name on the receipt line."
                                },
                                "quantity": {
                                    "type": "string",
                                    "description": "Decimal quantity (weights are fractional), no trailing zeros: \"3\", \"1.25\"."
                                },
                                "gross": {
                                    "$ref": "#/components/schemas/Money"
                                }
                            },
                            "required": [
                                "item_id",
                                "name",
                                "quantity",
                                "gross"
                            ]
                        }
                    }
                },
                "required": [
                    "date",
                    "location_id",
                    "orders",
                    "gross",
                    "discounts",
                    "service_charges",
                    "net",
                    "tax",
                    "tax_included",
                    "items"
                ]
            },
            "Event": {
                "type": "object",
                "properties": {
                    "id": {
                        "type": "string",
                        "example": "evt_01J8..."
                    },
                    "type": {
                        "type": "string",
                        "enum": [
                            "order.created",
                            "order.updated",
                            "order.status_changed",
                            "order.paid",
                            "order.cancelled",
                            "catalog.updated",
                            "stop_list.updated",
                            "location.updated",
                            "app.revoked"
                        ]
                    },
                    "created_at": {
                        "type": "string",
                        "format": "date-time"
                    },
                    "account_id": {
                        "$ref": "#/components/schemas/Id"
                    },
                    "data": {
                        "type": "object",
                        "properties": {
                            "object": {
                                "type": "string",
                                "enum": [
                                    "order",
                                    "catalog",
                                    "stop_list",
                                    "location",
                                    "grant"
                                ]
                            },
                            "id": {
                                "oneOf": [
                                    {
                                        "$ref": "#/components/schemas/Id"
                                    },
                                    {
                                        "type": "null"
                                    }
                                ]
                            },
                            "location_id": {
                                "oneOf": [
                                    {
                                        "$ref": "#/components/schemas/Id"
                                    },
                                    {
                                        "type": "null"
                                    }
                                ]
                            },
                            "status": {
                                "type": [
                                    "string",
                                    "null"
                                ]
                            }
                        }
                    }
                },
                "required": [
                    "id",
                    "type",
                    "created_at",
                    "account_id",
                    "data"
                ],
                "description": "Thin 'what changed' notification without personal data; fetch the object with the API. Delivered at least once, unordered; deduplicate by id."
            },
            "Deleted": {
                "type": "object",
                "description": "Tombstone in a `since` delta: the object was deleted, or left the list (hidden from the POS menu, no longer applies to the `location_id` filter). Only these three fields; a tombstone may name an id the client never received (the database keeps only the id of a physically deleted row) — ignore such ids.",
                "properties": {
                    "id": {
                        "$ref": "#/components/schemas/Id"
                    },
                    "deleted": {
                        "type": "boolean",
                        "const": true
                    },
                    "updated_at": {
                        "type": "string",
                        "format": "date-time",
                        "description": "When the deletion was recorded."
                    }
                },
                "required": [
                    "id",
                    "deleted",
                    "updated_at"
                ]
            },
            "DefaultTax": {
                "type": "object",
                "properties": {
                    "id": {
                        "$ref": "#/components/schemas/Id"
                    },
                    "name": {
                        "type": "string"
                    },
                    "rate": {
                        "type": "string",
                        "example": "8.875",
                        "description": "Percent."
                    },
                    "included": {
                        "type": "boolean",
                        "description": "false — added on top of prices (US sales tax); true — inside prices (VAT)."
                    },
                    "kind": {
                        "type": "string",
                        "enum": [
                            "tax",
                            "fee"
                        ],
                        "description": "Informational: a default fee row is applied exactly like a tax."
                    }
                },
                "required": [
                    "id",
                    "name",
                    "rate",
                    "included",
                    "kind"
                ]
            },
            "EffectiveTax": {
                "type": "object",
                "description": "The one tax the POS puts on a line with this item (see Taxes).",
                "properties": {
                    "tax_id": {
                        "$ref": "#/components/schemas/Id"
                    },
                    "name": {
                        "type": "string"
                    },
                    "rate": {
                        "type": "string",
                        "example": "8.875",
                        "description": "Percent."
                    },
                    "included": {
                        "type": "boolean",
                        "description": "true — inside the price (informational); false — added on top of the line total."
                    }
                },
                "required": [
                    "tax_id",
                    "name",
                    "rate",
                    "included"
                ]
            },
            "MenuWindow": {
                "type": "object",
                "description": "One schedule rule of a menu, in the location's local time, evaluated the way the POS does: open when the day the window starts is within starts_on…ends_on (inclusive; null — unbounded), is one of `days` (empty — every day), and the time is within opens…closes inclusive to the second (both null — all day). closes earlier than opens — overnight: the tail after midnight belongs to the start day.",
                "properties": {
                    "id": {
                        "$ref": "#/components/schemas/Id"
                    },
                    "name": {
                        "type": "string"
                    },
                    "days": {
                        "type": "array",
                        "items": {
                            "type": "string",
                            "enum": [
                                "mon",
                                "tue",
                                "wed",
                                "thu",
                                "fri",
                                "sat",
                                "sun"
                            ]
                        }
                    },
                    "opens": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "pattern": "^\\d{2}:\\d{2}:\\d{2}$",
                        "example": "11:00:00"
                    },
                    "closes": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "pattern": "^\\d{2}:\\d{2}:\\d{2}$",
                        "example": "15:00:00"
                    },
                    "starts_on": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "format": "date"
                    },
                    "ends_on": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "format": "date"
                    },
                    "location_ids": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/Id"
                        },
                        "description": "Locations this rule applies to."
                    }
                },
                "required": [
                    "id",
                    "name",
                    "days",
                    "opens",
                    "closes",
                    "starts_on",
                    "ends_on",
                    "location_ids"
                ]
            },
            "LimitedStock": {
                "type": "object",
                "description": "On sale with a limited remaining quantity.",
                "properties": {
                    "item_id": {
                        "$ref": "#/components/schemas/Id"
                    },
                    "remaining_quantity": {
                        "type": "string",
                        "example": "3",
                        "description": "Decimal string (kilograms for a weighted item)."
                    },
                    "until": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "format": "date-time"
                    }
                },
                "required": [
                    "item_id",
                    "remaining_quantity",
                    "until"
                ]
            },
            "StopList": {
                "type": "object",
                "properties": {
                    "location_id": {
                        "$ref": "#/components/schemas/Id"
                    },
                    "as_of": {
                        "type": "string",
                        "format": "date-time",
                        "description": "The moment the list was evaluated, in the location's time zone."
                    },
                    "data": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/StopListEntry"
                        },
                        "description": "Not for sale now. A stopped category is expanded to its items."
                    },
                    "limited": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/LimitedStock"
                        }
                    }
                },
                "required": [
                    "location_id",
                    "as_of",
                    "data",
                    "limited"
                ]
            },
            "OrderTax": {
                "type": "object",
                "description": "Taxes of the order summed by tax and inclusion (line rows and order-level rows of t_order_tax).",
                "properties": {
                    "tax_id": {
                        "oneOf": [
                            {
                                "$ref": "#/components/schemas/Id"
                            },
                            {
                                "type": "null"
                            }
                        ]
                    },
                    "name": {
                        "type": "string"
                    },
                    "amount": {
                        "$ref": "#/components/schemas/Money"
                    },
                    "included": {
                        "type": "boolean"
                    }
                },
                "required": [
                    "tax_id",
                    "name",
                    "amount",
                    "included"
                ]
            },
            "OrderLineModifier": {
                "type": "object",
                "properties": {
                    "id": {
                        "$ref": "#/components/schemas/Id"
                    },
                    "modifier_id": {
                        "oneOf": [
                            {
                                "$ref": "#/components/schemas/Id"
                            },
                            {
                                "type": "null"
                            }
                        ],
                        "description": "For orders made on the POS or through this API — the modifier option id (ModifierGroup.modifiers[].id); legacy integrations may store the modifier's item id."
                    },
                    "name": {
                        "type": "string"
                    },
                    "quantity": {
                        "type": "string",
                        "description": "On the whole line: option quantity × line quantity, as the POS stores it."
                    },
                    "unit_price": {
                        "$ref": "#/components/schemas/Money"
                    },
                    "total": {
                        "$ref": "#/components/schemas/Money"
                    }
                },
                "required": [
                    "id",
                    "modifier_id",
                    "name",
                    "quantity",
                    "unit_price",
                    "total"
                ]
            },
            "OrderLine": {
                "type": "object",
                "properties": {
                    "id": {
                        "$ref": "#/components/schemas/Id"
                    },
                    "item_id": {
                        "oneOf": [
                            {
                                "$ref": "#/components/schemas/Id"
                            },
                            {
                                "type": "null"
                            }
                        ]
                    },
                    "name": {
                        "type": "string"
                    },
                    "quantity": {
                        "type": "string",
                        "example": "2",
                        "description": "Decimal; negative on a void/return row the POS keeps next to the original."
                    },
                    "unit_price": {
                        "$ref": "#/components/schemas/Money"
                    },
                    "modifiers": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/OrderLineModifier"
                        }
                    },
                    "modifiers_total": {
                        "allOf": [
                            {
                                "$ref": "#/components/schemas/Money"
                            }
                        ],
                        "description": "Σ modifiers[].total."
                    },
                    "subtotal": {
                        "allOf": [
                            {
                                "$ref": "#/components/schemas/Money"
                            }
                        ],
                        "description": "The line amount before discounts: the item's own amount + modifiers_total (the POS's t_order.sum rows)."
                    },
                    "discount_total": {
                        "$ref": "#/components/schemas/Money"
                    },
                    "taxes": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/TaxLine"
                        },
                        "description": "0 or 1 entries for lines priced by the POS v2 or by this API."
                    },
                    "note": {
                        "type": [
                            "string",
                            "null"
                        ]
                    }
                },
                "required": [
                    "id",
                    "item_id",
                    "name",
                    "quantity",
                    "unit_price",
                    "modifiers",
                    "modifiers_total",
                    "subtotal",
                    "discount_total",
                    "taxes",
                    "note"
                ]
            },
            "QuoteLineModifier": {
                "type": "object",
                "properties": {
                    "modifier_id": {
                        "$ref": "#/components/schemas/Id"
                    },
                    "name": {
                        "type": "string"
                    },
                    "quantity": {
                        "type": "string",
                        "description": "On the whole line: option quantity × line quantity (as the order will store it)."
                    },
                    "unit_price": {
                        "allOf": [
                            {
                                "$ref": "#/components/schemas/Money"
                            }
                        ],
                        "description": "Option price plus the group surcharge (POS rule)."
                    },
                    "total": {
                        "$ref": "#/components/schemas/Money"
                    }
                },
                "required": [
                    "modifier_id",
                    "name",
                    "quantity",
                    "unit_price",
                    "total"
                ]
            },
            "PaymentSession": {
                "type": "object",
                "description": "A payment session: PalomaPOS asked the app to take a payment for an online order (QR menu). Statuses: `pending` (waiting for the guest), `paid`, `rejected`, `expired` (past `expires_at`; a late payment can still be resolved), `failed` (the app did not answer the create request per contract, or `failure_code: superseded` — replaced by a newer session or the order was paid by another one; a superseded session can still be resolved if the guest paid it).",
                "properties": {
                    "id": {
                        "type": "string",
                        "example": "pps_3f9a1c2b7d4e6f8091a2b3c4d5e6f708"
                    },
                    "status": {
                        "type": "string",
                        "enum": [
                            "pending",
                            "paid",
                            "rejected",
                            "expired",
                            "failed"
                        ]
                    },
                    "amount": {
                        "type": "string",
                        "pattern": "^\\d{1,12}\\.\\d{2}$",
                        "example": "5000.00"
                    },
                    "currency": {
                        "type": "string",
                        "example": "KZT"
                    },
                    "order_id": {
                        "type": "string"
                    },
                    "location_id": {
                        "type": [
                            "string",
                            "null"
                        ]
                    },
                    "reference": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "The app's payment id."
                    },
                    "settlement": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "enum": [
                            "applied",
                            "not_applied",
                            null
                        ],
                        "description": "After `paid`: `applied` — the order is paid and closed; `not_applied` — the payment is recorded on the session only (see settlement_reason), refund the guest."
                    },
                    "settlement_reason": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "enum": [
                            "order_not_found",
                            "order_closed",
                            "order_cancelled",
                            "amount_changed",
                            null
                        ]
                    },
                    "failure_code": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "Why the session is `rejected` (your reason) or `failed`."
                    },
                    "created_at": {
                        "type": "string",
                        "format": "date-time"
                    },
                    "expires_at": {
                        "type": "string",
                        "format": "date-time"
                    },
                    "resolved_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "format": "date-time"
                    }
                },
                "required": [
                    "id",
                    "status",
                    "amount",
                    "currency",
                    "order_id",
                    "location_id",
                    "reference",
                    "settlement",
                    "settlement_reason",
                    "failure_code",
                    "created_at",
                    "expires_at",
                    "resolved_at"
                ]
            },
            "PaymentSessionResolveInput": {
                "type": "object",
                "properties": {
                    "reference": {
                        "type": "string",
                        "minLength": 1,
                        "maxLength": 128,
                        "pattern": "^[\\x21-\\x7E]+$",
                        "description": "Your payment id (printable ASCII)."
                    },
                    "amount": {
                        "type": "string",
                        "pattern": "^\\d{1,12}\\.\\d{2}$",
                        "example": "5000.00",
                        "description": "Must equal the session amount."
                    }
                },
                "required": [
                    "reference",
                    "amount"
                ]
            },
            "PaymentSessionRejectInput": {
                "type": "object",
                "properties": {
                    "reason": {
                        "type": "string",
                        "enum": [
                            "declined",
                            "cancelled",
                            "expired",
                            "error"
                        ]
                    }
                },
                "required": [
                    "reason"
                ]
            },
            "PaymentAction": {
                "type": "object",
                "description": "What the guest sees on the QR menu payment page. Links are https only.",
                "properties": {
                    "type": {
                        "type": "string",
                        "enum": [
                            "qr",
                            "redirect"
                        ],
                        "description": "`qr` — show a QR code drawn from qr_payload (plus optional buttons); `redirect` — send the guest to url."
                    },
                    "qr_payload": {
                        "type": "string",
                        "maxLength": 2048,
                        "description": "Required for `qr`: the string encoded into the QR code (for Kaspi — the payment link)."
                    },
                    "url": {
                        "type": "string",
                        "format": "uri",
                        "maxLength": 2048,
                        "description": "Required for `redirect`; for `qr` — optional link to pay on the same phone."
                    },
                    "deep_links": {
                        "type": "array",
                        "maxItems": 4,
                        "items": {
                            "type": "object",
                            "properties": {
                                "label": {
                                    "type": "string",
                                    "maxLength": 40
                                },
                                "url": {
                                    "type": "string",
                                    "format": "uri"
                                }
                            },
                            "required": [
                                "label",
                                "url"
                            ]
                        }
                    }
                },
                "required": [
                    "type"
                ]
            },
            "PaymentSessionCreateRequest": {
                "type": "object",
                "description": "Sent by PalomaPOS to the app's payment session URL when a guest starts paying an online order.",
                "properties": {
                    "type": {
                        "type": "string",
                        "const": "payment_session.create"
                    },
                    "api_version": {
                        "type": "string",
                        "const": "1"
                    },
                    "id": {
                        "type": "string",
                        "description": "Payment session id (`pps_…`). Use it as your idempotency key: the same id may arrive again."
                    },
                    "created_at": {
                        "type": "string",
                        "format": "date-time"
                    },
                    "expires_at": {
                        "type": "string",
                        "format": "date-time",
                        "description": "Suggested deadline; your expires_at in the response wins within 2–30 minutes."
                    },
                    "test": {
                        "type": "boolean",
                        "description": "true on the sandbox host (sandbox-api.paloma365.com): do not take real money."
                    },
                    "account_id": {
                        "type": "string",
                        "description": "The PalomaPOS account — the same account_id your token response returned when the owner connected your app."
                    },
                    "location_id": {
                        "type": "string"
                    },
                    "order": {
                        "type": "object",
                        "properties": {
                            "id": {
                                "type": "string"
                            },
                            "number": {
                                "type": "string"
                            },
                            "type": {
                                "type": "string",
                                "enum": [
                                    "dine_in",
                                    "pickup",
                                    "delivery"
                                ]
                            }
                        },
                        "required": [
                            "id",
                            "number",
                            "type"
                        ]
                    },
                    "amount": {
                        "type": "string",
                        "pattern": "^\\d{1,12}\\.\\d{2}$",
                        "example": "5000.00"
                    },
                    "currency": {
                        "type": "string",
                        "example": "KZT"
                    },
                    "description": {
                        "type": "string",
                        "maxLength": 60,
                        "example": "Заказ №42"
                    }
                },
                "required": [
                    "type",
                    "api_version",
                    "id",
                    "created_at",
                    "expires_at",
                    "test",
                    "account_id",
                    "location_id",
                    "order",
                    "amount",
                    "currency",
                    "description"
                ]
            },
            "PaymentSessionCreateResponse": {
                "type": "object",
                "properties": {
                    "reference": {
                        "type": "string",
                        "minLength": 1,
                        "maxLength": 128
                    },
                    "action": {
                        "$ref": "#/components/schemas/PaymentAction"
                    },
                    "expires_at": {
                        "type": "string",
                        "format": "date-time",
                        "description": "Until when the guest can start paying (RFC 3339 with an offset). Clamped to 2–30 minutes from now; default 15 minutes."
                    }
                },
                "required": [
                    "reference",
                    "action"
                ]
            },
            "SandboxPaymentSessionInput": {
                "type": "object",
                "additionalProperties": false,
                "description": "All fields are optional (an empty body is fine). Sandbox host only.",
                "properties": {
                    "amount": {
                        "type": "string",
                        "pattern": "^\\d{1,8}(\\.\\d{1,2})?$",
                        "default": "1000.00",
                        "description": "Session amount in the account currency (decimal string), more than 0 and at most 10000000.00. Default 1000.00; required with `replaces` and must differ from the replaced session."
                    },
                    "order_type": {
                        "type": "string",
                        "enum": [
                            "dine_in",
                            "pickup",
                            "delivery"
                        ],
                        "default": "pickup"
                    },
                    "settlement": {
                        "type": "string",
                        "enum": [
                            "applied",
                            "order_cancelled",
                            "order_closed",
                            "amount_changed",
                            "order_not_found"
                        ],
                        "default": "applied",
                        "description": "What resolving the session does: `applied`, or `not_applied` with this reason (the order could not take the payment — refund the guest)."
                    },
                    "replaces": {
                        "type": "string",
                        "pattern": "^pps_[0-9a-f]{32}$",
                        "description": "Your own waiting test session: it is superseded and the new session (with a new `amount`) is for the same test order. Not together with `order_type` or `settlement`."
                    },
                    "checks": {
                        "type": "boolean",
                        "default": true,
                        "description": "false — send only the real request (no invalid-signature and retry checks)."
                    }
                }
            },
            "SandboxCheck": {
                "type": "object",
                "required": [
                    "result",
                    "detail"
                ],
                "properties": {
                    "result": {
                        "type": "string",
                        "enum": [
                            "passed",
                            "failed",
                            "skipped"
                        ]
                    },
                    "detail": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "What is wrong and how to fix it; null when passed"
                    }
                }
            },
            "SandboxPaymentSessionResult": {
                "type": "object",
                "required": [
                    "session",
                    "test_order",
                    "delivery"
                ],
                "description": "Sandbox host only.",
                "properties": {
                    "session": {
                        "$ref": "#/components/schemas/PaymentSession"
                    },
                    "test_order": {
                        "type": "object",
                        "required": [
                            "id",
                            "number",
                            "type",
                            "settlement"
                        ],
                        "properties": {
                            "id": {
                                "type": "string",
                                "description": "`order.id` in the request we sent; the order exists only in the sandbox"
                            },
                            "number": {
                                "type": "string",
                                "example": "TEST-58"
                            },
                            "type": {
                                "type": "string",
                                "enum": [
                                    "dine_in",
                                    "pickup",
                                    "delivery"
                                ]
                            },
                            "settlement": {
                                "type": "string",
                                "enum": [
                                    "applied",
                                    "order_cancelled",
                                    "order_closed",
                                    "amount_changed",
                                    "order_not_found"
                                ]
                            }
                        }
                    },
                    "delivery": {
                        "type": "object",
                        "required": [
                            "request",
                            "checks"
                        ],
                        "properties": {
                            "request": {
                                "type": "object",
                                "required": [
                                    "url",
                                    "headers",
                                    "body"
                                ],
                                "description": "Exactly what was sent to your session_url (the valid request).",
                                "properties": {
                                    "url": {
                                        "type": "string"
                                    },
                                    "headers": {
                                        "type": "object",
                                        "additionalProperties": {
                                            "type": "string"
                                        }
                                    },
                                    "body": {
                                        "type": "string",
                                        "description": "The raw body, byte for byte — the signature is HMAC-SHA256 over \"<t>.<body>\""
                                    }
                                }
                            },
                            "checks": {
                                "type": "object",
                                "required": [
                                    "signature",
                                    "response",
                                    "retry"
                                ],
                                "properties": {
                                    "signature": {
                                        "$ref": "#/components/schemas/SandboxCheck"
                                    },
                                    "response": {
                                        "$ref": "#/components/schemas/SandboxCheck"
                                    },
                                    "retry": {
                                        "$ref": "#/components/schemas/SandboxCheck"
                                    }
                                }
                            }
                        }
                    }
                }
            },
            "SandboxReadiness": {
                "type": "object",
                "required": [
                    "ready",
                    "next",
                    "checks"
                ],
                "description": "Sandbox host only.",
                "properties": {
                    "ready": {
                        "type": "boolean",
                        "description": "Every check passed"
                    },
                    "next": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "Id of the first check that has not passed"
                    },
                    "checks": {
                        "type": "array",
                        "items": {
                            "type": "object",
                            "required": [
                                "id",
                                "status",
                                "detail",
                                "checked_at",
                                "how"
                            ],
                            "properties": {
                                "id": {
                                    "type": "string",
                                    "enum": [
                                        "connection",
                                        "signature",
                                        "session_response",
                                        "retry",
                                        "resolve_applied",
                                        "resolve_not_applied",
                                        "reject"
                                    ]
                                },
                                "status": {
                                    "type": "string",
                                    "enum": [
                                        "passed",
                                        "failed",
                                        "not_run"
                                    ]
                                },
                                "detail": {
                                    "type": [
                                        "string",
                                        "null"
                                    ]
                                },
                                "checked_at": {
                                    "type": [
                                        "string",
                                        "null"
                                    ],
                                    "format": "date-time"
                                },
                                "how": {
                                    "type": "string",
                                    "description": "What to do to pass this check"
                                }
                            }
                        }
                    }
                }
            }
        },
        "headers": {
            "X-Request-Id": {
                "description": "Id of this request (`req_` + 24 hex). Quote it when you contact support.",
                "schema": {
                    "type": "string"
                }
            },
            "PalomaPOS-Api-Version": {
                "description": "Major version of the API that answered.",
                "schema": {
                    "type": "string",
                    "example": "1"
                }
            },
            "Retry-After": {
                "description": "Seconds to wait before retrying.",
                "schema": {
                    "type": "integer"
                }
            },
            "Idempotent-Replayed": {
                "description": "`true` when the response is the stored result of an earlier request with the same `Idempotency-Key`.",
                "schema": {
                    "type": "string",
                    "enum": [
                        "true"
                    ]
                }
            }
        },
        "responses": {
            "InternalError": {
                "description": "internal_error — unexpected; retry with backoff (same Idempotency-Key for writes) and quote `request_id` if it persists",
                "content": {
                    "application/json": {
                        "schema": {
                            "$ref": "#/components/schemas/Error"
                        },
                        "example": {
                            "error": {
                                "code": "internal_error",
                                "message": "Unexpected error. Quote request_id to support.",
                                "retryable": true,
                                "request_id": "req_4f1c2a9be07d5e8a1b3c6d20",
                                "details": {}
                            }
                        }
                    }
                }
            },
            "Unavailable": {
                "description": "`temporarily_unavailable` (retryable, `Retry-After`) — a dependency is busy; or `account_not_ready` (not retryable) — this business account's database has not been upgraded for the API yet: tell the owner or support, do not retry in a loop",
                "content": {
                    "application/json": {
                        "schema": {
                            "$ref": "#/components/schemas/Error"
                        },
                        "example": {
                            "error": {
                                "code": "account_not_ready",
                                "message": "This business account's database has not been upgraded for the API yet. Quote request_id to support.",
                                "retryable": false,
                                "request_id": "req_4f1c2a9be07d5e8a1b3c6d20",
                                "details": {}
                            }
                        }
                    }
                },
                "headers": {
                    "Retry-After": {
                        "$ref": "#/components/headers/Retry-After"
                    }
                }
            }
        }
    },
    "externalDocs": {
        "description": "Integration guide (Markdown): OAuth, conventions, sync, idempotency, rate limits, orders, errors",
        "url": "guide.md"
    }
}
