Reference
Authentication & conventions
Everything that applies to every endpoint: how to authenticate, the limits, and how responses are shaped.
Authentication
Every request carries an Authorization: Bearer header with a key you mint in your dashboard. Keys look like oac_live_…, are scoped to your company, and are shown once at creation — store them securely. A missing, malformed, or revoked key returns 401.
Authorization: Bearer oac_live_3f9a…c1e7
Every read is automatically scoped to your company's restaurants — you can never see another tenant's data, even by guessing an id. Mint or revoke keys in API keys.
Rate limits
60 requests per minute per API key. Every response carries the current budget; over-limit requests get 429 with a Retry-After (seconds).
X-RateLimit-Limit: 60 X-RateLimit-Remaining: 41 X-RateLimit-Reset: 1734556800 Retry-After: 17 # only on 429
Need a higher ceiling for a bulk sync? Talk to us.
Errors
Errors use standard HTTP status codes and a JSON body with a human-readable error.
{ "error": "Restaurant not found" }| Status | Meaning |
|---|---|
| 200 / 201 | Success. POSTs that create a resource return 201. |
| 400 | Malformed request — bad JSON or invalid/missing fields. |
| 401 | Missing, malformed, or revoked API key. |
| 404 | Resource not found, or not owned by your company. |
| 409 | Conflict — bookings disabled, or the slot is fully booked. |
| 429 | Rate limit exceeded. Back off using Retry-After. |
| 5xx | Transient server error — retry with backoff. |
Pagination
List endpoints are cursor-paginated. Pass limit (default 50, max 100) and follow nextCursor until it's null. Never rely on offsets.
let cursor = null;
do {
const url = new URL("https://openalacarte.com/api/v1/bookings");
url.searchParams.set("limit", "100");
if (cursor) url.searchParams.set("cursor", cursor);
const { data, nextCursor } = await (await fetch(url, {
headers: { Authorization: `Bearer ${process.env.OAC_API_KEY}` },
})).json();
handle(data);
cursor = nextCursor;
} while (cursor);Versioning & stability
- The API is versioned in the URL (
/api/v1/…). Breaking changes ship asv2alongsidev1. v1stays online for at least 12 months after any deprecation notice.- Additive changes (new fields, endpoints, webhook events) are not breaking — tolerate unknown fields.
- All timestamps are ISO-8601 in UTC.
Generate a typed SDK or import into Postman from the OpenAPI 3.0 spec.