Pick by route
The two credentials are not interchangeable. Sending an OAuth bearer to
/restaurants (or the /check_ins venue feed) returns an empty-body 401
— no API key present. Sending an API key to /users/me/check_ins is
rejected the same way: a member’s own history always needs their token.
Both return 401 with the reason in the WWW-Authenticate header, not
JSON.
What each credential authorizes
The API key is issued per partner, per environment, and grants app-level read access to Discovery data. The OAuth access token acts on behalf of the member who completed the flow. Member routes resolve the subject from the token’ssub claim, so
/users/me/* returns that member’s data, never another member’s.
OAuth scopes
Member routes are gated by scope. A token without the required scope returns403 with WWW-Authenticate: Bearer error="insufficient_scope":
the route still exists; the token simply isn’t authorized for it.
These are OAuth (JWT) scopes, requested at
/authorize. The
/check_ins venue feed and /check_ins/{id} are API-key routes
gated by the separate read:checkins scope minted on the key — not an
OAuth scope. See API keys.
The member who completed the OAuth flow is the token’s sub claim.
See Identify the authenticated member.
Credential lifetimes
How credentials reach you
After your app is approved, Blackbird sends your credentials by email — a set scoped to staging. Production credentials are issued separately when you’re approved for live traffic; see Environments.
If anything is missing or wrong, reply to the onboarding email;
fixes are fast pre-launch. See OAuth for the
full OAuth flow and API keys for
server-to-server use.
401 behavior
The 401 envelope is determined by the route family’s gating filter, not by which credential you happened to send.- OAuth-protected routes (
/users/me/*,/payment_intents/*) return HTTP 401 with an empty body on missing, malformed, or expired bearer. This also happens if you accidentally send an API key here: the OAuth filter doesn’t see a bearer and rejects. Do not try to parse JSON. - API-key routes (
/restaurants*,/locations*, the/check_insvenue feed,/check_ins/{id}) return the same empty-body 401 when the API key is missing. An invalid (expired or revoked) key is the one case that returns a JSON body — envelope A withcode: "invalid_api_key". See Pagination + errors for the exact shapes.
error_code
mapped to cause and fix.
Choose your on-ramp
Hello API Key
One curl, one API key, confirm Discovery works.
Hello OAuth
One curl, one access token, confirm a member route works.