Authenticate
Send the one-time API key as a Bearer token. OrderDock stores its digest, never the reusable plaintext value.
Preparing orders...
OrderDock developer platform
Issue a key once, select only the scopes an integration needs, and subscribe an HTTPS endpoint to versioned restaurant events. Keys and webhook secrets are shown once, hashed or encrypted at rest, rate limited, audited, and individually revocable.
Send the one-time API key as a Bearer token. OrderDock stores its digest, never the reusable plaintext value.
Use orders:read for redacted order projections and menu:read for published menu versions. A missing scope is denied.
Every request is tenant scoped and audited. The API enforces a durable per-client rate limit and returns a correlation ID.
Read API
GET/api/v1/developer/orders
Redacted order state, totals, channel, and timestamps. No guest email, phone, address, or payment credentials.
GET/api/v1/developer/menu
Published menu versions and channel-ready menu data. Draft content is excluded.
Request example
curl https://orderdock.ca/api/v1/developer/orders?limit=25 \
-H "Authorization: Bearer $ORDERDOCK_API_KEY"Signed webhooks
Delivery uses a per-subscription secret, HMAC-SHA256, a timestamped v1 signature, no redirects, retry backoff, and a durable replay log. Return a 2xx response only after your receiver has durably accepted the event.
Endpoint registration rejects non-HTTPS, loopback, link-local, private-network, and credential-bearing URLs. Delivery repeats that network check before connecting.
Node.js verification example
import { createHmac, timingSafeEqual } from "node:crypto";
export function verifyOrderDock(rawBody, signature, secret) {
const parts = Object.fromEntries(
signature.split(",").map((part) => part.split("=", 2))
);
const timestamp = parts.t;
const supplied = parts.v1;
if (!timestamp || !supplied || Math.abs(Date.now() / 1000 - Number(timestamp)) > 300) {
return false;
}
const expected = createHmac("sha256", secret)
.update(`${timestamp}.${rawBody}`)
.digest("hex");
return supplied.length === expected.length &&
timingSafeEqual(Buffer.from(supplied), Buffer.from(expected));
}order.submitted.v1order.accept.v1order.fulfillment-advance.v1order.complete.v1order.cancel.v1kitchen.ready.v1payment.captured.v1menu.version.publish.v1menu.import.reconciled.v1Errors use RFC 9457-style problem details with a stable code, status, human-readable detail, retryability, and correlation ID. A 401 means the key is invalid or expired; 403 means its scope is insufficient; 429 means the client rate window is exhausted.
The URL and event name carry the major version. Additive fields may appear without a major change. Breaking changes receive a new major version and a documented migration window in the changelog.