Authentication

Every way to authenticate to Kentro in one place: API key headers, bearer tokens, buyer and guest tokens, Pixel keys and OAuth for Kentro MCP.

Every request is authenticated at Kentro's gateway before it reaches an API: the gateway resolves the credential to a tenant and its scopes, and refuses anything else with 401. Which credential to send depends on who is calling: a system, a storefront acting for a buyer, a website or backend sending events, or an AI assistant acting for a user.

Which method to use

CallerAPICredentialSent as
A server-to-server integrationChannel APIAPI key pairkentro-key and kentro-secret headers
An integration making many calls, or a component that must not hold the secretChannel API, Pixel management APIBearer token minted from the key pairAuthorization: Bearer <accessToken>
A custom storefront's serverStore APIAPI key holding storefront:serve, plus the storefront hostX-API-Key and X-Storefront-Host
A signed-in buyer on that storefrontStore APIBuyer access tokenX-Storefront-Buyer
A guest shopper on that storefrontStore APIGuest tokenX-Storefront-Guest
A website or app sending eventsKentro Pixel collectorProperty public keyThe SDK's data-key
A backend sending eventsKentro Pixel server APIHMAC server keyX-Kentro-Key-Id, X-Kentro-Timestamp, X-Kentro-Signature
An AI assistant acting for a Kentro userKentro MCPOAuth 2.1 access tokenAuthorization: Bearer, managed by the MCP client

Every credential belongs to one tenant, and nothing in a request selects a tenant: the credential's tenant is the tenant of the call.

API key headers

The Channel API takes the key pair from Users > API keys on every request:

kentro-key: <key>
kentro-secret: <secret>

X-API-Key: <secret> is the single-header form: the secret alone. The gateway compares it against every active key, so prefer the pair, or a bearer token, at high request rates. The Store API takes only this form.

Bearer tokens and refresh

Exchange the key pair once for an access token that lives 15 minutes.

curl -s -X POST https://apis.kentro.live/auth/login/api-key \
  -H "Content-Type: application/json" \
  -d '{ "key": "'"$KENTRO_KEY"'", "secret": "'"$KENTRO_SECRET"'" }'
const res = await fetch('https://apis.kentro.live/auth/login/api-key', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({ key: process.env.KENTRO_KEY, secret: process.env.KENTRO_SECRET }),
});
if (!res.ok) throw new Error(`login failed: ${res.status} ${await res.text()}`);
const { accessToken, refreshToken, expiresIn } = await res.json();
console.log({ expiresIn, hasRefreshToken: Boolean(refreshToken), tokenPrefix: accessToken.slice(0, 12) });

The answer:

{
  "accessToken": "eyJhbGciOi...",
  "refreshToken": "4f2c7a...",
  "expiresIn": 900,
  "user": { "id": "...", "tenantId": "...", "type": "api-key" }
}

Send Authorization: Bearer <accessToken> on Channel API calls. Before expiresIn seconds pass, rotate the pair:

curl -s -X POST https://apis.kentro.live/auth/refresh \
  -H "Content-Type: application/json" \
  -d '{ "refreshToken": "'"$REFRESH_TOKEN"'" }'
  • The answer holds a new access token and a new refresh token. The refresh token rotates on every use; a refresh token used twice is refused.
  • A key issued as a single token logs in with { "apiKeyRaw": "<token>" } instead of key and secret.
  • POST https://apis.kentro.live/auth/logout with { "refreshToken": "..." } revokes a refresh token.
  • An expired access token answers 401 TOKEN_EXPIRED: refresh, then retry. A malformed one answers 401 TOKEN_INVALID.
  • On the sandbox the host is https://apis.kentro.dev.

A bearer token skips the per-request secret check, which matters at many requests per second, and keeps the secret in one place.

Store API: key, host, buyer and guest

A Store API request carries up to three identities.

IdentityHeaderWhere it comes from
The storefront serverX-API-Key (the key's secret)Users > API keys, with a permission group holding storefront:serve
The storeX-Storefront-HostThe published storefront's host, lower case, no scheme, no path
The buyerX-Storefront-Buyer: <accessToken>POST https://apis.kentro.live/auth/login/customer with { "email", "password", "host" }
The guestX-Storefront-Guest: <guestToken>POST /session.guest
  • Buyer access tokens live 15 minutes; buyer refresh tokens live 30 days and rotate on every POST /auth/refresh. Refresh before expiry, or on the first 401.
  • Buyer sign-in, refresh, sign-out and password reset take no API key; host in the body names the store.
  • The Store API does not read Authorization. The buyer token travels in X-Storefront-Buyer, never as a bearer token.
  • Mint a guest token once per browser, and only when store.get answers guestCheckout: true. Right after sign-in, send both tokens so the guest's cart can be offered to the buyer.
  • A password change ends every session of the buyer's account.

Details: Store API: Authentication.

Kentro Pixel keys

KeyFormatUsed by
Public keypk_live_... for production properties, pk_test_... for staging and development propertiesThe browser SDK. Visible in page source by design; limited to the property's allowed origins.
Server keyAn sk_ key id plus a secret shown onceA backend: signs POST https://pixel.kentro.live/v1/server/events with HMAC-SHA256 over timestamp + "." + rawBody, within a 300-second window, and signs identity tokens for signed-in visitors.
Kentro authenticationA bearer token or an API key holding pixel:read or pixel:manageThe Pixel management API at https://apis.kentro.live/pixel/v1.

See Pixel server API, Identity tokens for signed-in visitors and Pixel browser SDK.

OAuth for Kentro MCP

Kentro MCP lets an AI assistant work with a tenant's data as one Kentro user. It uses OAuth 2.1; no API key is involved.

  1. The MCP client calls the Kentro MCP server and receives 401 with a WWW-Authenticate header that points to the server's OAuth metadata. The metadata names Kentro's authentication service (https://apis.kentro.live/auth) as the authorization server.
  2. The client registers itself (dynamic client registration) and starts an authorization code flow with PKCE. Only the S256 challenge method is accepted.
  3. The user signs in to Kentro and approves the client on the Connect to Kentro Assistant page (Approve or Deny).
  4. The client exchanges the code for an access token (1 hour, expires_in: 3600, scope copilot) and a refresh token, and refreshes on its own.
  • The connection acts with the approving user's permissions, in that user's tenant.
  • The user revokes the connection in Kentro IQ under Assistant > Assistant Settings, panel Connect your AI tools (MCP). A revoked grant's tokens are refused, and it cannot mint new ones.

Setup per client: Connect Claude and Connect coding agents. Controls: MCP security.

What the gateway answers

Refusals before a request reaches an API use the gateway's shape, { "error", "message" }:

StatuserrorCause
401INVALID_REQUESTNo credentials where a key is required, such as a Store API call without X-API-Key.
401INVALID_CREDENTIALSUnknown or disabled key, or a wrong secret.
401TOKEN_INVALIDA malformed bearer token.
401TOKEN_EXPIREDA bearer token past its lifetime: refresh.
403TENANT_INACTIVEThe tenant is deactivated.

A Channel API request with no credentials at all reaches the API and answers 401 with code: unauthenticated in the API's own envelope. Branch on error or code, never on message: the INVALID_CREDENTIALS message mentions an email and a password even when the credential was an API key.


Did this page help you?