Skip to content

Partner API

Partner API changelog

Every integrator-visible change to the Partner API, newest first.

Versioning policy

The v1 API only changes additively: new endpoints, new optional parameters, new response fields, new event types, new error codes. Nothing documented is removed or repurposed within v1. A breaking change means a new versioned base path, announced here with a migration window first.

Releases

  1. Added

    Partner API v1

    • REST under https://api.trueplate.ai/v1: /partner/me, the restaurants a key may read, the full menu payload with ETag conditional requests, item listings, item detail with short-TTL signed USDZ/GLB URLs, and asset URL refresh.
    • Incremental sync: item listings sweep a FIXED window, meta.syncWindowStart / meta.syncWindowEnd report the range each poll covered, and feeding syncWindowEnd back as the next updatedAfter is gapless and overlap-free. Deletions arrive as tombstones, and meta.fullResyncRequired says outright when the feed can no longer converge, instead of leaving you to guess against a retention number.
    • Cursor pagination on the collections that grow without bound (restaurants, items, webhook deliveries), all with the same { data, meta.nextCursor } envelope. Cursors are signed and bound to the filters that issued them, so reusing one with different filters returns 400 cursor_filter_mismatch rather than a silently different page. status cannot be combined with updatedAfter: a status-filtered incremental feed would miss items as they leave the filtered status, so sync unfiltered and filter client-side.
    • AI concierge: POST /partner/restaurants/{restaurantId}/concierge/chat runs one grounded diner turn against the restaurant's menu and streams it as Server-Sent Events (meta, delta, cards, detail, done, error), the exact protocol TruePlate's own menu pages consume. There is no raw-completion mode, no system-prompt override and no model parameter. Keep the AI disclosure carried in meta visible to your end users: under EU AI Act Article 50 the obligation follows the deployment surface, which is yours.
    • Webhooks: signed deliveries (X-TruePlate-Signature, Stripe-style t/v1 scheme), 8 delivery attempts with exponential backoff, secret rotation, and endpoint auto-disable on sustained failure. GET /partner/webhook-deliveries walks the full retention window, newest first. Events that fire while a restaurant's subscription is lapsed are held for 72 hours and delivered on renewal rather than dropped.
    • Embeddable 3D viewer: the <trueplate-viewer> web component, authenticated with a publishable key under a per-key Origin allowlist. AR on phones (Quick Look on iOS, Scene Viewer on Android), inline 3D on the web.
    • Embeddable concierge: the <trueplate-concierge> web component, same publishable key and Origin allowlist. It renders nothing at all when the restaurant's concierge is not servable, so an unentitled restaurant never shows a dead button, and its cards deep-link to the public TruePlate menu, AR included.
    • Key scopes: menu:read, assets:read, webhooks:manage, concierge:chat. Each operation's requirement is declared in the OpenAPI document's security block, so the reference states the scope rather than leaving you to infer it. Concierge chat additionally requires the restaurant's own AI Concierge to be switched on, and each turn draws on that restaurant's concierge message allowance.
    • Test mode: create a key in the Test environment for a tp_sk_test_ / tp_pk_test_ token that reaches the same data with the same permissions, is never billed, runs under fixed caps (60 requests/minute, 5,000/day) and streams a deterministic concierge sandbox that spends no model tokens. Every response carries X-TruePlate-Environment: live|test.
    • Idempotency-Key on mutating endpoints, Stripe semantics: durable across infrastructure restarts, bound to the operation and request body, 24h replay window, and 409 idempotency_key_conflict if a key is reused for a different request.
    • Rate-limit headers (X-RateLimit-Limit / X-RateLimit-Remaining / X-RateLimit-Reset, Retry-After) on every response. Monthly allowances are enforced atomically and return 429 quota_exceeded once exhausted. Serving above the included allowance is the restaurant's own pay-as-you-go setting, opt-in and capped, so an integration cannot raise its own ceiling.
    • Item lookups by id return 404 for anything your key cannot reach, indistinguishable from a missing id, so the API never confirms that an item you have no access to exists.
    • Integrator keys reach every restaurant with an active owner-approved grant, established through a connect link the owner consents to. Restaurant keys reach exactly their own restaurant.