GLOSSARY

What is a Bearer Token?

A bearer token is a credential that grants access to whoever presents it, sent as an Authorization header of the form "Bearer <token>" per RFC 6750, with no proof required that the sender is the party the token was issued to.

Free forever plan · No credit card required · Cancel anytime

Quick definition

A bearer token is a credential that grants access to whoever presents it, sent as an Authorization header of the form "Bearer <token>" per RFC 6750, with no proof required that the sender is the party the token was issued to.

On the wire it is one line: Authorization: Bearer psk_live_...

What it means

A bearer token is a string that means "let this request through". The server checks the string, not the sender. There is no signature to verify, no key exchange, no challenge and response. Presenting the token is the authentication.

RFC 6750, "The OAuth 2.0 Authorization Framework: Bearer Token Usage", defines the mechanics and states the security model in one sentence: any party in possession of a bearer token can use it. The metaphor is a banknote. The bank does not ask who you are, and a note that falls out of your pocket is spendable by whoever finds it.

Everything else about bearer tokens is a consequence of that sentence. Use TLS, because anyone who reads the token owns it. Keep them out of URLs, because URLs are logged. Keep them out of browsers, because devtools is a log. Scope them narrowly, because a stolen token does whatever the token was allowed to do. Make them revocable, because you will eventually need to kill one at two in the morning.

Where the token goes

RFC 6750 defines three transmission methods, and only the first should be used in new work.

  • Section 2.1, the Authorization header. Authorization: Bearer <token>. The scheme name is case-insensitive as an HTTP auth scheme, but write it as Bearer because some servers compare it naively. This is the method to use.
  • Section 2.2, a form-encoded body parameter. Allowed for constrained clients that cannot set headers. Requires a specific content type and rules out sending anything else in the body, so it is rarely useful.
  • Section 2.3, a URI query parameter. Defined, and marked NOT RECOMMENDED in the specification itself. URLs end up in access logs, proxy logs, browser history and, for a long time, in the Referer header sent to third parties. A token in a URL is a token that has been written down in half a dozen places you do not control.

The Pinlyx Data API accepts a key in a header only, either as a bearer token or as the equivalent x-api-key header for clients where that is more convenient. Both carry the same value; neither is a query parameter.

The token's own grammar

RFC 6750 defines the token value as b64token: one or more characters from ALPHA, DIGIT, -, ., _, ~, +, /, followed by optional = padding. No spaces, no colons, no commas. That constraint is why nearly every API key you have seen is letters, digits and underscores, and it is what makes a prefix like psk_live_ both legal and useful.

The prefix is not decoration. Secret scanners in source hosts, CI systems and log pipelines match on distinctive prefixes, so a token that starts with a recognisable marker gets caught when it is committed by accident. A separate psk_test_ prefix for test keys buys a second thing: a test key that reaches production fails loudly instead of quietly spending real budget.

Opaque, self-contained, or sender-constrained

"Bearer" describes how the token is transmitted, not what is inside it. Three families exist, and the choice is a real trade-off rather than a matter of taste.

An opaque token is a random string that means nothing outside the issuer's own store. Every request costs a lookup, which is the price of the property that matters most in practice: revocation is instant. Delete the row and the very next request fails.

A JWT carries its own claims and signature, so a resource server can verify it without asking anyone. RFC 9068 profiles exactly this for OAuth 2.0 access tokens. The cost is that you cannot un-issue it: a JWT stays valid until it expires unless you add a denylist, at which point you have paid for the lookup you were avoiding. Short lifetimes plus refresh is the usual compromise.

A sender-constrained token binds the credential to a key the client holds, via mutual TLS (RFC 8705) or DPoP (RFC 9449). A thief who copies the token but not the key gets nothing. This is strictly stronger, and it is still uncommon in data APIs because it pushes key management onto every integrator.

What the server says when it refuses

RFC 6750 section 3.1 defines a WWW-Authenticate challenge and three error codes, and the mapping to status codes is the part worth memorising:

  • invalid_request with 400: the request itself is malformed, for example two authentication methods at once.
  • invalid_token with 401: missing, expired, revoked or malformed credential. Re-authenticating might help.
  • insufficient_scope with 403: the token is genuinely valid and still not allowed to do this. Re-authenticating cannot help; the credential needs a different scope.

That last distinction is why 401 and 403 must not be used interchangeably. A client that receives 401 will refresh its credential and try again, which is precisely the wrong response to a scope problem and produces an infinite loop of successful authentications followed by identical refusals.

The Data API expresses the same distinctions in its own envelope: 401 with code unauthorized or invalid_key, and 403 with code forbidden_scope. It adds a fourth that RFC 6750 does not model at all: forbidden_ip, when a valid key with the right scope is used from an address outside its allowlist. That is a sender constraint bolted onto a bearer scheme, and it is one of the cheapest ways to blunt the impact of a leak.

Handling rules that actually matter

  • TLS, always. RFC 6750 requires it. A bearer token sent over plain HTTP is a credential published to every hop on the path.
  • Never in front-end code. An API key is a server-to-server credential. Anyone who opens devtools on a page that carries one has your whole quota. Call the API from your own backend and forward the result.
  • Never in a log. Redact the Authorization header at the logging layer, not at each call site, because the call site you forget is the one that ships.
  • One key per job. Separate keys per environment, per service and per integration mean a leak is contained and revocation does not take everything else down with it.
  • Rotate on a schedule you have actually rehearsed. A rotation procedure that has never been run is not a procedure.

Related concepts

  • API scope: what limits the damage a stolen token can do.
  • HMAC signature: the other authentication model, where a leaked value is worthless on its own.
  • Rate limit: the ceilings that are counted per key rather than per user.
  • Webhook: the inbound direction, where you verify rather than present a credential.

How Pinlyx handles it

Data API keys are opaque, prefixed psk_live_ for production and psk_test_ for test, minted in the panel in about a minute, and revocable instantly. A key carries the scopes your plan allows and a rate tier, and it can be restricted to an IP allowlist. Send it as a bearer token or as x-api-key, over TLS, from your own backend. A revoked key produces a 401 with the code invalid_key and a message that says exactly that, so an expired credential is never mistaken for an outage.

Cheat sheet · presenting the token

Two accepted headers, and three ways to be refused.

The request
# Preferred: RFC 6750 section 2.1
curl https://pinlyx.com/data-api/v2/accounts/instagram/nasa \
  -H "Authorization: Bearer psk_live_..."

# Equivalent, for clients where a plain header is easier
curl https://pinlyx.com/data-api/v2/accounts/instagram/nasa \
  -H "x-api-key: psk_live_..."

# Never. Section 2.3 defines this and marks it NOT RECOMMENDED.
curl "https://pinlyx.com/data-api/v2/accounts/instagram/nasa?api_key=psk_live_..."
401 · bad credential
HTTP/1.1 401 Unauthorized

{
  "error": {
    "code": "invalid_key",
    "message": "This API key has
      been revoked.",
    "request_id": "req_9f2c41a8b3d5"
  }
}
403 · valid, not allowed
HTTP/1.1 403 Forbidden

{
  "error": {
    "code": "forbidden_scope",
    "message": "This key does not
      carry the leads:read scope
      required by this endpoint.",
    "request_id": "req_9f2c41a8b3d5"
  }
}
403 · wrong address
HTTP/1.1 403 Forbidden

{
  "error": {
    "code": "forbidden_ip",
    "message": "This request came
      from an address outside the
      key's allowlist.",
    "request_id": "req_9f2c41a8b3d5"
  }
}

Three refusals, three different fixes: mint a new key, add a scope, add the address. A client that collapses all of them into "auth failed" will retry the one case where retrying can never work.

What is inside the token

The revocation column is the one that decides most arguments.

KindVerificationRevocationWire cost
Opaque (a random string)A lookup in the issuer store on every request.Immediate. Delete the row and the next request fails.Small. Typically 32 to 64 characters.
Self-contained (JWT)Signature check, no lookup. RFC 9068 profiles this for OAuth access tokens.Not before expiry, unless you add a denylist and reintroduce the lookup.Large. Several hundred bytes to a few KB on every request.
Sender-constrained (mTLS, DPoP)Token plus proof of possession of a key. RFC 8705 and RFC 9449.As per the underlying token, but a stolen token alone is useless.Adds a handshake or a per-request proof.
Watch out for

Seven ways a bearer token leaks.

  • In a query string, where it lands in access logs, proxy logs and browser history.
  • In front-end JavaScript, where devtools is a public log of your entire quota.
  • In a mobile app binary, which anyone can unpack. Assume any key shipped to a device is public.
  • In an error report or a stack trace that includes request headers.
  • In a screenshot pasted into a support ticket, which is why the panel should never redisplay a key.
  • In a shared key used by every customer of a reselling integration, so revoking one revokes all of them.
  • In a commit, which is exactly what a distinctive psk_live_ prefix exists to let scanners catch.

Bearer tokens: FAQ

The spec, the status codes, and the handling rules that stop a leak from becoming an incident.

The name is borrowed from bearer instruments in finance, such as a bearer bond or a banknote: whoever physically holds it can spend it, and no identity check is performed. RFC 6750 says so almost in those words, describing a bearer token as one that any party in possession of it can use. Every security practice around bearer tokens follows from that one property, which is why the practices are all about possession: TLS, no logging, no URLs, short lifetimes, narrow scopes.
RFC 6750 section 2.3 defines a URI query parameter method and then says it is NOT RECOMMENDED, which in RFC language is close to a prohibition. The reasons are concrete: full URLs land in web server access logs, in proxy logs, in browser history, and historically in the Referer header sent to third parties. The Pinlyx Data API accepts a key only in a header, either as Authorization: Bearer or as x-api-key, and never as a query parameter.
RFC 6750 defines the b64token syntax: one or more of ALPHA, DIGIT, "-", ".", "_", "~", "+", "/", followed by any number of "=" padding characters. So a token cannot contain a space, a colon or a comma. That is why practically every API key you have seen uses a prefix built from letters, digits and underscores, such as psk_live_ for production keys and psk_test_ for test keys.
Automated leak detection. Secret scanners built into source hosts, CI pipelines and log processors match on distinctive prefixes, so psk_live_ is recognisable as a credential in a way that a bare 40-character hex string is not. A separate test prefix is worth as much operationally: a test key that reaches production fails loudly rather than quietly spending real budget against real data.
RFC 6750 section 3.1 maps them precisely. invalid_token, meaning missing, expired, revoked or malformed, gets 401 Unauthorized and a WWW-Authenticate challenge. insufficient_scope, meaning the token is valid but does not carry the permission this endpoint requires, gets 403 Forbidden. The distinction matters because a client that sees 401 will try to re-authenticate, and re-authenticating cannot fix a missing scope. In the Pinlyx Data API those surface as 401 with code invalid_key or unauthorized, and 403 with code forbidden_scope.
Yes, and knowingly so. A sender-constrained token bound to a client key via mTLS (RFC 8705) or DPoP (RFC 9449) is worthless to a thief who does not also hold the key; a bearer token is fully usable by anyone who copies it out of a log line. The industry keeps choosing bearer for server-to-server APIs because it needs no key management on the client side and works through any HTTP stack. The trade is operational simplicity for a larger blast radius on leak, which is why leak handling has to be a designed feature: distinctive prefixes, instant revocation, scopes and IP allowlists.
Ready to ship

One key. Scoped, revocable, and never in a URL.

Prefixed keys, instant revocation, per-key scopes and an optional IP allowlist across all 127 endpoints of the Pinlyx Data API.

Free forever plan · GDPR-ready · No credit card required

We value your privacy

We use cookies to improve our site, analyze traffic, and personalize ads. You can accept all, reject non-essential, or customize your choices. Read our Cookie Policy.