Developer docs

Authentication

How BookDinePlay API keys work — publishable versus secret, where each is allowed, how to send them, and what the API refuses.

Every call to /api/venues/** must present an API key. There is no anonymous tier. A key is scoped to one venue: it works for that venue's routes and is refused for every other.

Two key types

Publishable bdp_pk_… Secret bdp_sk_…
Lives in Your public HTML, the widget, the WordPress plugin Your server only
Protected by An origin allowlist you maintain Being secret (stored as a SHA-256 hash; shown once at creation)
Origin header Required — a browser sent it Forbidden — a browser must never hold it
Typical caller The booking widget in a guest's browser Your back end, using the .NET SDK or plain HTTP

Create and revoke keys in the console under Venue → API keys (app.bookdineplay.com/operator/venue). A publishable key's value is visible there at any time; a secret key's value is shown exactly once.

Sending a key

Either header works; the widget and the SDK use the first:

X-BookDinePlay-Key: bdp_pk_your_publishable_key
Authorization: Bearer bdp_pk_your_publishable_key

Never put a key in a query string. A key in a URL ends up in access logs, Referer headers and browser history, and the API does not read it from there anyway.

curl

curl "https://api.bookdineplay.com/api/venues/your-venue" \
  -H "X-BookDinePlay-Key: bdp_pk_your_publishable_key" \
  -H "Origin: https://www.your-venue.example"

JavaScript

const response = await fetch('https://api.bookdineplay.com/api/venues/your-venue', {
  headers: { 'X-BookDinePlay-Key': 'bdp_pk_your_publishable_key' }
});
const venue = await response.json();

C#

// Program.cs — server-side, with a SECRET key from configuration, never a literal.
builder.Services.AddBookDinePlayClient(
    new Uri("https://api.bookdineplay.com"),
    builder.Configuration["BookDinePlay:ApiKey"]!);

// Anywhere IBookDinePlayClient is injected:
var venue = await client.GetVenueAsync("your-venue", cancellationToken);

Origins

A publishable key carries a list of allowed origins. An origin is scheme://host[:port]https://www.your-venue.example, not a path, and not a bare host name. Matching is exact on scheme and host; the port must match too, unless the entry ends in :*:

http://localhost:*
https://staging.your-venue.example:*

:* means "any port on exactly this scheme and host" — for local development on localhost, or a staging host that moves between ports. It is the only wildcard; there is no wildcard for scheme, host or subdomain.

A request whose Origin is on the list gets that origin back in Access-Control-Allow-Origin and the data it asked for; one that is not gets a 403 whose problem body the browser can still read — the API echoes your origin on rejections precisely so you can see the type — but no venue data. The allowlist is the CORS policy — there is no separate setting.

What the API refuses

Every refusal is an RFC 7807 problem response whose type ends in the reason below; each reason has its own section on Errors.

Status type suffix When Fix
401 missing-api-key No key in either header Send the key
401 invalid-api-key Unknown, revoked, or wrong-prefix key Check the key in the console
403 venue-mismatch The key belongs to a different venue than the route names Use that venue's key
403 origin-not-allowed Publishable key; the request's Origin is not on its list Create a key that lists the origin — a key's list is fixed at creation
403 secret-key-from-browser Secret key and an Origin header — a browser sent it Use a publishable key in browsers
403 publishable-key-without-origin Publishable key and no Origin — a server sent it Use a secret key on servers

Unknown and revoked keys give the same answer on purpose: nobody can probe which one it is.

{
  "type": "https://bookdineplay.com/docs/api/errors/origin-not-allowed",
  "title": "Forbidden",
  "status": 403,
  "detail": "This origin is not on the API key's list of allowed origins."
}

Rotating a key

Keys can coexist, so rotation never needs downtime:

  1. Create a new key of the same type with the same origins.
  2. Deploy it to your site or server.
  3. Revoke the old key in the console. Revocation is immediate.

Next steps

  • Quickstart — put a publishable key to work in the widget.
  • .NET SDK — server-side use with a secret key.