OrderDock developer platform

Restaurant data with narrow permissions and durable delivery.

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.

Authenticate

Send the one-time API key as a Bearer token. OrderDock stores its digest, never the reusable plaintext value.

Authorize

Use orders:read for redacted order projections and menu:read for published menu versions. A missing scope is denied.

Operate

Every request is tenant scoped and audited. The API enforces a durable per-client rate limit and returns a correlation ID.

Read API

Stable v1 resources

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

Verify the raw request before parsing it.

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.v1

Error contract

Errors 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.

Version policy

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.