{"openapi":"3.0.3","info":{"title":"DigiMenu Platform API","version":"1.1.0","description":"Third-party app API, verified against controllers and services on 2026-09-27. OAuth authorization-code + PKCE S256, rotating refresh tokens, one restaurant per installation. Guide: https://digimenu.us/gelistiriciler. API version remains /api/v1; 1.1.0 is the documentation revision.","contact":{"url":"https://digimenu.us/iletisim"}},"servers":[{"url":"https://api.digimenu.us","description":"TEST and LIVE apps use the same API; TEST restricts installation to the developer organization, not a separate data sandbox."}],"tags":[{"name":"health"},{"name":"oauth"},{"name":"me"},{"name":"menu"},{"name":"orders"},{"name":"tables"},{"name":"webhooks"},{"name":"deliveries"}],"paths":{"/api/v1/health":{"get":{"operationId":"get__health","tags":["health"],"summary":"Service health","description":"","security":[],"parameters":[],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Health"}}}}}}},"/api/v1/oauth/token":{"post":{"operationId":"post__oauth_token","tags":["oauth"],"summary":"Exchange an authorization code or rotate tokens","description":"JSON only in these examples. No client_credentials grant. PKCE S256 is mandatory, even for confidential clients. Serialize refresh operations per installation; old refresh-token reuse revokes the refresh family.","security":[],"parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TokenRequest"}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TokenResponse"}}}},"400":{"description":"invalid_request / invalid_grant","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OAuthError"}}}},"401":{"description":"invalid_client","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OAuthError"}}}},"403":{"description":"access_denied: app application requires DigiMenu approval, including TEST mode","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OAuthError"}}}},"429":{"description":"30 requests per minute per IP","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationError"}}}}}}},"/api/v1/me":{"get":{"operationId":"get__me","tags":["me"],"summary":"Read the token’s installation context","description":"","security":[{"bearer":[]}],"parameters":[],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Me"}}}},"400":{"description":"Invalid request or resource state","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/Error"},{"$ref":"#/components/schemas/ValidationError"}]}}}},"401":{"description":"Missing/expired token, revoked installation, or app removed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"APP_APPROVAL_REQUIRED (including TEST), missing scope, inactive subscription or delivery restriction","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Resource not found within the installation","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate or hourly quota exceeded","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/Error"},{"$ref":"#/components/schemas/ValidationError"}]}}}}}}},"/api/v1/menu":{"get":{"operationId":"get__menu","tags":["menu"],"summary":"Read active categories and products","description":"No pagination. Does not expose recipe cost, inventory, variants or internal preparation data.","security":[{"bearer":[]}],"x-required-scope":"menu:read","parameters":[],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Menu"}}}},"400":{"description":"Invalid request or resource state","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/Error"},{"$ref":"#/components/schemas/ValidationError"}]}}}},"401":{"description":"Missing/expired token, revoked installation, or app removed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"APP_APPROVAL_REQUIRED (including TEST), missing scope, inactive subscription or delivery restriction","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Resource not found within the installation","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate or hourly quota exceeded","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/Error"},{"$ref":"#/components/schemas/ValidationError"}]}}}}}}},"/api/v1/tables":{"get":{"operationId":"get__tables","tags":["tables"],"summary":"Read active tables","description":"Returns a bare array. Does not expose QR secrets, sessions or occupancy.","security":[{"bearer":[]}],"x-required-scope":"tables:read","parameters":[],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/Table"}}}}},"400":{"description":"Invalid request or resource state","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/Error"},{"$ref":"#/components/schemas/ValidationError"}]}}}},"401":{"description":"Missing/expired token, revoked installation, or app removed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"APP_APPROVAL_REQUIRED (including TEST), missing scope, inactive subscription or delivery restriction","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Resource not found within the installation","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate or hourly quota exceeded","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/Error"},{"$ref":"#/components/schemas/ValidationError"}]}}}}}}},"/api/v1/orders":{"get":{"operationId":"get__orders","tags":["orders"],"summary":"List orders, newest first","description":"","security":[{"bearer":[]}],"x-required-scope":"orders:read","parameters":[{"name":"limit","in":"query","required":false,"description":"Page size.","schema":{"type":"integer","minimum":1,"maximum":100,"default":25}},{"name":"cursor","in":"query","required":false,"description":"Pass the previous nextCursor unchanged. Stop when null.","schema":{"type":"string","maxLength":64}},{"name":"channel","in":"query","required":false,"description":"Order channel.","schema":{"type":"string","enum":["TABLE","TAKEAWAY","DELIVERY"]}},{"name":"status","in":"query","required":false,"description":"Use a known order status, e.g. OUT_FOR_DELIVERY; omit for all statuses.","schema":{"type":"string","maxLength":40}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrderPage"}}}},"400":{"description":"Invalid request or resource state","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/Error"},{"$ref":"#/components/schemas/ValidationError"}]}}}},"401":{"description":"Missing/expired token, revoked installation, or app removed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"APP_APPROVAL_REQUIRED (including TEST), missing scope, inactive subscription or delivery restriction","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Resource not found within the installation","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate or hourly quota exceeded","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/Error"},{"$ref":"#/components/schemas/ValidationError"}]}}}}}}},"/api/v1/orders/{id}":{"get":{"operationId":"get__orders__id_","tags":["orders"],"summary":"Read an order","description":"","security":[{"bearer":[]}],"x-required-scope":"orders:read","parameters":[{"name":"id","in":"path","required":true,"description":"Resource identifier.","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Order"}}}},"400":{"description":"Invalid request or resource state","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/Error"},{"$ref":"#/components/schemas/ValidationError"}]}}}},"401":{"description":"Missing/expired token, revoked installation, or app removed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"APP_APPROVAL_REQUIRED (including TEST), missing scope, inactive subscription or delivery restriction","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Resource not found within the installation","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate or hourly quota exceeded","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/Error"},{"$ref":"#/components/schemas/ValidationError"}]}}}}}}},"/api/v1/orders/{id}/transitions":{"post":{"operationId":"post__orders__id__transitions","tags":["orders"],"summary":"Update a delivery-leg order status","description":"ASSIGNED_TO_COURIER → OUT_FOR_DELIVERY → DELIVERED or DELIVERY_FAILED. Same status is a no-op. This generic route does not run courier GPS/proof checks: courier apps should use /deliveries. No payment, kitchen, cancel, create-order or refund operation is exposed.","security":[{"bearer":[]}],"x-required-scope":"orders:write","parameters":[{"name":"id","in":"path","required":true,"description":"Resource identifier.","schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":false,"description":"Optional. Unique per installation AND operation. A response is cached for 5 minutes in one process; not durable across restarts. Never reuse for another order or body.","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Transition"}}}},"responses":{"201":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Order"}}}},"400":{"description":"Invalid request or resource state","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/Error"},{"$ref":"#/components/schemas/ValidationError"}]}}}},"401":{"description":"Missing/expired token, revoked installation, or app removed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"APP_APPROVAL_REQUIRED (including TEST), missing scope, inactive subscription or delivery restriction","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Resource not found within the installation","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"INVALID_TRANSITION","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate or hourly quota exceeded","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/Error"},{"$ref":"#/components/schemas/ValidationError"}]}}}}}}},"/api/v1/webhooks":{"get":{"operationId":"get__webhooks","tags":["webhooks"],"summary":"List this app’s webhook endpoints","description":"App-wide, not restaurant-specific. Register once per app, not once per installation.","security":[{"bearer":[]}],"x-required-scope":"webhooks:manage","parameters":[],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/WebhookEndpoint"}}}}},"400":{"description":"Invalid request or resource state","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/Error"},{"$ref":"#/components/schemas/ValidationError"}]}}}},"401":{"description":"Missing/expired token, revoked installation, or app removed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"APP_APPROVAL_REQUIRED (including TEST), missing scope, inactive subscription or delivery restriction","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Resource not found within the installation","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate or hourly quota exceeded","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/Error"},{"$ref":"#/components/schemas/ValidationError"}]}}}}}},"post":{"operationId":"post__webhooks","tags":["webhooks"],"summary":"Register a webhook receiver","description":"No idempotency-key support. Check GET /webhooks before retrying a create after a network timeout; a duplicate request creates another endpoint. Secret is returned once.","security":[{"bearer":[]}],"x-required-scope":"webhooks:manage","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateWebhook"}}}},"responses":{"201":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookCreated"}}}},"400":{"description":"Invalid request or resource state","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/Error"},{"$ref":"#/components/schemas/ValidationError"}]}}}},"401":{"description":"Missing/expired token, revoked installation, or app removed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"APP_APPROVAL_REQUIRED (including TEST), missing scope, inactive subscription or delivery restriction","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Resource not found within the installation","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate or hourly quota exceeded","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/Error"},{"$ref":"#/components/schemas/ValidationError"}]}}}}}}},"/api/v1/webhooks/{id}":{"delete":{"operationId":"delete__webhooks__id_","tags":["webhooks"],"summary":"Disable a webhook endpoint","description":"Soft disable; repeating for your already-disabled endpoint succeeds. No public re-enable endpoint: register a new endpoint and store its new secret.","security":[{"bearer":[]}],"x-required-scope":"webhooks:manage","parameters":[{"name":"id","in":"path","required":true,"description":"Resource identifier.","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DisabledWebhook"}}}},"400":{"description":"Invalid request or resource state","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/Error"},{"$ref":"#/components/schemas/ValidationError"}]}}}},"401":{"description":"Missing/expired token, revoked installation, or app removed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"APP_APPROVAL_REQUIRED (including TEST), missing scope, inactive subscription or delivery restriction","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Resource not found within the installation","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate or hourly quota exceeded","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/Error"},{"$ref":"#/components/schemas/ValidationError"}]}}}}}}},"/api/v1/webhooks/{id}/deliveries":{"get":{"operationId":"get__webhooks__id__deliveries","tags":["webhooks"],"summary":"Read delivery attempts for this app’s endpoint","description":"","security":[{"bearer":[]}],"x-required-scope":"webhooks:manage","parameters":[{"name":"id","in":"path","required":true,"description":"Resource identifier.","schema":{"type":"string"}},{"name":"limit","in":"query","required":false,"description":"Page size.","schema":{"type":"integer","minimum":1,"maximum":100,"default":25}},{"name":"cursor","in":"query","required":false,"description":"Pass the previous nextCursor unchanged. Stop when null.","schema":{"type":"string","maxLength":64}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookDeliveryPage"}}}},"400":{"description":"Invalid request or resource state","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/Error"},{"$ref":"#/components/schemas/ValidationError"}]}}}},"401":{"description":"Missing/expired token, revoked installation, or app removed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"APP_APPROVAL_REQUIRED (including TEST), missing scope, inactive subscription or delivery restriction","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Resource not found within the installation","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate or hourly quota exceeded","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/Error"},{"$ref":"#/components/schemas/ValidationError"}]}}}}}}},"/api/v1/deliveries/{runId}":{"get":{"operationId":"get__deliveries__runId_","tags":["deliveries"],"summary":"Read a run assigned to this app","description":"Requires a courier installation created by granting deliveries:write. Reads only that installation’s courier runs.","security":[{"bearer":[]}],"x-required-scope":"deliveries:read","parameters":[{"name":"runId","in":"path","required":true,"description":"Resource identifier.","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Run"}}}},"400":{"description":"Invalid request or resource state","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/Error"},{"$ref":"#/components/schemas/ValidationError"}]}}}},"401":{"description":"Missing/expired token, revoked installation, or app removed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"APP_APPROVAL_REQUIRED (including TEST), missing scope, inactive subscription or delivery restriction","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Resource not found within the installation","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate or hourly quota exceeded","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/Error"},{"$ref":"#/components/schemas/ValidationError"}]}}}}}}},"/api/v1/deliveries/{runId}/depart":{"post":{"operationId":"post__deliveries__runId__depart","tags":["deliveries"],"summary":"Start an assigned run","description":"ASSIGNED → ON_ROUTE. Moves assigned orders to OUT_FOR_DELIVERY. A second depart fails with INVALID_RUN_STATE; reconcile GET before retrying.","security":[{"bearer":[]}],"x-required-scope":"deliveries:write","parameters":[{"name":"runId","in":"path","required":true,"description":"Resource identifier.","schema":{"type":"string"}}],"responses":{"201":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DepartResult"}}}},"400":{"description":"Invalid request or resource state","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/Error"},{"$ref":"#/components/schemas/ValidationError"}]}}}},"401":{"description":"Missing/expired token, revoked installation, or app removed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"APP_APPROVAL_REQUIRED (including TEST), missing scope, inactive subscription or delivery restriction","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Resource not found within the installation","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate or hourly quota exceeded","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/Error"},{"$ref":"#/components/schemas/ValidationError"}]}}}}}}},"/api/v1/deliveries/{runId}/pings":{"post":{"operationId":"post__deliveries__runId__pings","tags":["deliveries"],"summary":"Send a courier location","description":"The implementation resolves the active run from the authenticated courier and does not use runId to select a run. Send your assigned active run ID. Pings may be dropped with stored=false / THROTTLED; do not immediately retry.","security":[{"bearer":[]}],"x-required-scope":"deliveries:write","parameters":[{"name":"runId","in":"path","required":true,"description":"Resource identifier.","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Ping"}}}},"responses":{"201":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PingResult"}}}},"400":{"description":"Invalid request or resource state","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/Error"},{"$ref":"#/components/schemas/ValidationError"}]}}}},"401":{"description":"Missing/expired token, revoked installation, or app removed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"APP_APPROVAL_REQUIRED (including TEST), missing scope, inactive subscription or delivery restriction","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Resource not found within the installation","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate or hourly quota exceeded","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/Error"},{"$ref":"#/components/schemas/ValidationError"}]}}}}}}},"/api/v1/deliveries/orders/{orderId}/delivered":{"post":{"operationId":"post__deliveries_orders__orderId__delivered","tags":["deliveries"],"summary":"Confirm delivery with location and proof","description":"Requires assigned order OUT_FOR_DELIVERY, fresh GPS near drop-off, and restaurant-selected proof. CODE requires code; PHOTO/SIGNATURE require a platform-issued upload unavailable through public v1. Do not treat these modes as a complete external-only integration.","security":[{"bearer":[]}],"x-required-scope":"deliveries:write","parameters":[{"name":"orderId","in":"path","required":true,"description":"Resource identifier.","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Delivered"}}}},"responses":{"201":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Ok"}}}},"400":{"description":"Invalid request or resource state","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/Error"},{"$ref":"#/components/schemas/ValidationError"}]}}}},"401":{"description":"Missing/expired token, revoked installation, or app removed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"APP_APPROVAL_REQUIRED (including TEST), missing scope, inactive subscription or delivery restriction","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Resource not found within the installation","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate or hourly quota exceeded","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/Error"},{"$ref":"#/components/schemas/ValidationError"}]}}}}}}},"/api/v1/deliveries/orders/{orderId}/failed":{"post":{"operationId":"post__deliveries_orders__orderId__failed","tags":["deliveries"],"summary":"Report a failed delivery","description":"Requires an assigned OUT_FOR_DELIVERY order. No general idempotency header support; reconcile order state after an ambiguous response.","security":[{"bearer":[]}],"x-required-scope":"deliveries:write","parameters":[{"name":"orderId","in":"path","required":true,"description":"Resource identifier.","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Failed"}}}},"responses":{"201":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Ok"}}}},"400":{"description":"Invalid request or resource state","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/Error"},{"$ref":"#/components/schemas/ValidationError"}]}}}},"401":{"description":"Missing/expired token, revoked installation, or app removed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"APP_APPROVAL_REQUIRED (including TEST), missing scope, inactive subscription or delivery restriction","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Resource not found within the installation","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate or hourly quota exceeded","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/Error"},{"$ref":"#/components/schemas/ValidationError"}]}}}}}}}},"components":{"securitySchemes":{"bearer":{"type":"http","scheme":"bearer","bearerFormat":"JWT","description":"OAuth app access token. Dashboard login tokens cannot be used here."}},"schemas":{"Error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"requiredScope":{"type":"string"}},"required":["code","message"]},"ValidationError":{"type":"object","properties":{"statusCode":{"type":"integer"},"message":{"oneOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}]},"error":{"type":"string"}},"required":["statusCode","message"]},"OAuthError":{"type":"object","properties":{"error":{"type":"string"},"error_description":{"type":"string"}},"required":["error","error_description"]},"TokenRequest":{"type":"object","properties":{"grant_type":{"type":"string","enum":["authorization_code","refresh_token"]},"client_id":{"type":"string","maxLength":200},"client_secret":{"type":"string","description":"Required if a client secret has been configured.","maxLength":200},"code":{"type":"string","description":"Required for authorization_code; single use, valid for 60 seconds.","maxLength":200},"redirect_uri":{"type":"string","description":"Required for authorization_code. Exact registered URL.","maxLength":500,"format":"uri"},"code_verifier":{"type":"string","description":"Required for authorization_code. Original PKCE verifier.","minLength":43,"maxLength":128},"refresh_token":{"type":"string","description":"Required for refresh_token grant.","maxLength":200}},"required":["grant_type","client_id"]},"TokenResponse":{"type":"object","properties":{"access_token":{"type":"string"},"refresh_token":{"type":"string"},"token_type":{"type":"string","enum":["Bearer"]},"expires_in":{"type":"integer","example":3600},"scope":{"type":"string","description":"Space-separated granted permissions."}},"required":["access_token","refresh_token","token_type","expires_in","scope"]},"Restaurant":{"type":"object","properties":{"slug":{"type":"string"},"name":{"type":"string"}},"required":["slug","name"]},"Me":{"type":"object","properties":{"installationId":{"type":"string"},"appId":{"type":"string"},"restaurantId":{"type":"string"},"scopes":{"type":"array","items":{"type":"string","enum":["menu:read","orders:read","orders:write","tables:read","deliveries:read","deliveries:write","customers:read","webhooks:manage"]}},"mode":{"type":"string","enum":["TEST","LIVE"]},"restaurant":{"type":"object","properties":{"slug":{"type":"string"},"name":{"type":"string"}},"required":["slug","name"],"nullable":true}},"required":["installationId","appId","restaurantId","scopes","mode","restaurant"]},"Product":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"description":{"type":"string","nullable":true},"price":{"type":"number","description":"Major currency units, not minor units. Currency is not included in this response."},"isActive":{"type":"boolean"},"order":{"type":"integer"},"allergens":{"type":"string","nullable":true}},"required":["id","name","description","price","isActive","order","allergens"]},"Category":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"order":{"type":"integer"},"products":{"type":"array","items":{"$ref":"#/components/schemas/Product"}}},"required":["id","name","order","products"]},"Menu":{"type":"object","properties":{"restaurant":{"$ref":"#/components/schemas/Restaurant"},"categories":{"type":"array","items":{"$ref":"#/components/schemas/Category"}}},"required":["restaurant","categories"]},"Table":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"tableNumber":{"type":"integer"}},"required":["id","name","tableNumber"]},"OrderItem":{"type":"object","properties":{"name":{"type":"string"},"quantity":{"type":"integer"},"note":{"type":"string","nullable":true}},"required":["name","quantity","note"]},"Order":{"type":"object","properties":{"id":{"type":"string"},"shortId":{"type":"string"},"channel":{"type":"string","enum":["TABLE","TAKEAWAY","DELIVERY"]},"status":{"type":"string"},"createdAt":{"type":"string","format":"date-time"},"scheduledFor":{"type":"string","format":"date-time","nullable":true},"deliveryAddress":{"type":"object","nullable":true,"additionalProperties":true,"description":"Coarse locality with contactRedacted=true by default. Exact address/contact is returned only with customers:read AND assignment to this app’s courier."},"deliveryFeeMinor":{"type":"integer","description":"Minor currency units; currency not included.","nullable":true},"items":{"type":"array","items":{"$ref":"#/components/schemas/OrderItem"}},"courierRef":{"type":"string","nullable":true}},"required":["id","shortId","channel","status","createdAt","scheduledFor","deliveryAddress","deliveryFeeMinor","items","courierRef"]},"OrderPage":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Order"}},"nextCursor":{"type":"string","nullable":true}},"required":["data","nextCursor"]},"Transition":{"type":"object","properties":{"status":{"type":"string","enum":["OUT_FOR_DELIVERY","DELIVERED","DELIVERY_FAILED"]}},"required":["status"]},"WebhookEndpoint":{"type":"object","properties":{"id":{"type":"string"},"url":{"type":"string","format":"uri"},"events":{"type":"array","items":{"type":"string","enum":["order.created","order.paid","delivery.ready","delivery.assigned","delivery.picked_up","delivery.delivered","delivery.failed"]}},"active":{"type":"boolean"},"disabledAt":{"type":"string","format":"date-time","nullable":true},"createdAt":{"type":"string","format":"date-time"}},"required":["id","url","events","active","disabledAt","createdAt"]},"WebhookCreated":{"allOf":[{"$ref":"#/components/schemas/WebhookEndpoint"},{"type":"object","properties":{"secret":{"type":"string","description":"Signing secret; returned once at creation."}},"required":["secret"]}]},"CreateWebhook":{"type":"object","properties":{"url":{"type":"string","description":"Public HTTPS URL on port 443; credentials, redirects and private hosts are rejected.","format":"uri","maxLength":2048},"events":{"type":"array","items":{"type":"string","enum":["order.created","order.paid","delivery.ready","delivery.assigned","delivery.picked_up","delivery.delivered","delivery.failed"],"maxLength":64},"minItems":1}},"required":["url","events"]},"DisabledWebhook":{"type":"object","properties":{"id":{"type":"string"},"active":{"type":"boolean","enum":[false]}},"required":["id","active"]},"WebhookDelivery":{"type":"object","properties":{"id":{"type":"string"},"eventType":{"type":"string"},"status":{"type":"string","enum":["PENDING","DELIVERED","FAILED"]},"attempts":{"type":"integer"},"responseCode":{"type":"integer","nullable":true},"lastError":{"type":"string","nullable":true},"createdAt":{"type":"string","format":"date-time"}},"required":["id","eventType","status","attempts","responseCode","lastError","createdAt"]},"WebhookDeliveryPage":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/WebhookDelivery"}},"nextCursor":{"type":"string","nullable":true}},"required":["data","nextCursor"]},"WebhookEvent":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"type":{"type":"string","enum":["order.created","order.paid","delivery.ready","delivery.assigned","delivery.picked_up","delivery.delivered","delivery.failed"]},"createdAt":{"type":"string","format":"date-time"},"restaurantId":{"type":"string"},"installationId":{"type":"string"},"data":{"type":"object","additionalProperties":true,"description":"Event-specific payload. Fetch the resource for current state. delivery.assigned is reserved; no producer is currently implemented."}},"required":["id","type","createdAt","restaurantId","installationId","data"]},"Run":{"type":"object","properties":{"id":{"type":"string"},"status":{"type":"string"},"startedAt":{"type":"string","format":"date-time","nullable":true},"completedAt":{"type":"string","format":"date-time","nullable":true},"routeDistanceMeters":{"type":"integer","nullable":true},"routeDurationSeconds":{"type":"integer","nullable":true},"orders":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"status":{"type":"string"}},"required":["id","status"]}},"location":{"type":"object","properties":{"lat":{"type":"number"},"lng":{"type":"number"},"at":{"type":"string","format":"date-time"}},"required":["lat","lng","at"],"nullable":true}},"required":["id","status","startedAt","completedAt","routeDistanceMeters","routeDurationSeconds","orders","location"]},"Ping":{"type":"object","properties":{"lat":{"type":"number","minimum":-90,"maximum":90},"lng":{"type":"number","minimum":-180,"maximum":180},"accuracyM":{"type":"number"},"headingDeg":{"type":"number"},"speedMps":{"type":"number"},"recordedAt":{"type":"string","format":"date-time"}},"required":["lat","lng"]},"PingResult":{"oneOf":[{"type":"object","properties":{"stored":{"type":"boolean","enum":[true]},"requeried":{"type":"boolean"}},"required":["stored","requeried"]},{"type":"object","properties":{"stored":{"type":"boolean","enum":[false]},"reason":{"type":"string","enum":["THROTTLED"]}},"required":["stored","reason"]}]},"Delivered":{"type":"object","properties":{"code":{"type":"string","description":"Required when the restaurant uses CODE proof mode.","maxLength":16},"proofRef":{"type":"string","description":"PHOTO/SIGNATURE require a platform-issued upload. The public v1 API has no proof-upload endpoint; do not submit an arbitrary URL.","maxLength":500}},"required":[]},"Failed":{"type":"object","properties":{"reason":{"type":"string","enum":["CUSTOMER_ABSENT","WRONG_ADDRESS","CUSTOMER_REJECTED","OTHER"]},"note":{"type":"string","description":"Accepted by validation; currently not persisted by the delivery service.","maxLength":200}},"required":["reason"]},"Ok":{"type":"object","properties":{"ok":{"type":"boolean"}},"required":["ok"]},"DepartResult":{"type":"object","properties":{"ok":{"type":"boolean"},"orders":{"type":"integer"}},"required":["ok","orders"]},"Health":{"type":"object","properties":{"status":{"type":"string","enum":["ok"]},"service":{"type":"string","enum":["api-v1"]},"ts":{"type":"string","format":"date-time"}},"required":["status","service","ts"]}}}}