Access Tokens

An access token is a credential that reaches one order and nothing else. You mint one on your server with createAccessToken, hand it to a page the public can open, and it stops working on its own after a few minutes.

This is what makes an order page or the Refund Manager embed safe to put on the open web. An API key scoped to orders:read reads every order on your sales agent, and anyone who views the page can copy it out of the markup. An access token copied out of the same page reaches the single order it was minted for, until it expires.

What a Token Can Do

A token carries one or both capabilities, chosen when you mint it:

CapabilityGrants
READRead the order, its bookings, its refunds and its payments
WRITEStart a refund of the order, and pay for it through the payment gateway (Stripe)

WRITE implies READ, so a token minted with capabilities: [WRITE] comes back carrying both — a credential that may refund an order may read it.

With those capabilities a token reaches these operations and no others:

Everything else is rejected with NOT_AUTHORIZED. That includes anything about your sales agent or your cost centers, wherever it appears in a query, so a page carrying a token cannot reveal your commercial setup. Any id other than the bound order's resolves as a missing node, so a token cannot be used to find out which of your orders exist.

A token also grants nothing its minting key did not already hold. Minting is refused unless the key could itself do everything the token is asked for: read the order for READ, and refund it and pay for it through the payment gateway for WRITE. Wallet and invoice payments are never available to a token, whatever the minting key holds. A token cannot mint another token either, so a page holding one cannot extend its own access.

Minting a Token

Mint on your server, never in the browser. The key you mint with needs the base scope for the environment you are in (live or test) and orders:read, plus payments:stripe for a WRITE token — minting must not hand out a payment method the key itself cannot use. See API Scopes for all three.

graphql
mutation CreateAccessToken {
  createAccessToken(
    restrictions: { orderId: "order_429682g2t6m0x2x4y224g002d5" }
    capabilities: [READ, WRITE]
    ttlSeconds: 900
  ) {
    id
    token
    capabilities
    expiresAt
  }
}
mutation CreateAccessToken {
  createAccessToken(
    restrictions: { orderId: "order_429682g2t6m0x2x4y224g002d5" }
    capabilities: [READ, WRITE]
    ttlSeconds: 900
  ) {
    id
    token
    capabilities
    expiresAt
  }
}
ArgumentDescription
restrictionsWhat the token is narrowed to. Must name an order, as an Order.id. Required
capabilitiesWhat the token may do. Omit it for [READ]. An explicitly empty list fails with INVALID_CAPABILITIES
ttlSecondsHow long the token lives, in seconds. Between 1 and 86400 (24 hours), 900 by default. Outside that range it fails with INVALID_TTL

You can mint for any order you can read with node. An orderId that names anything else — an order that does not exist, one that is not yours, or one whose booking never completed — fails with NOT_FOUND, without distinguishing the cases. Empty restrictions fails with INVALID_RESTRICTIONS.

The secret is returned once

token carries the secret exactly once, on what createAccessToken returns. It is stored only as a hash, so nothing can hand it back afterwards — reading the same token back with node returns token: null. If you lose it, mint another.

Mint a fresh token each time you render the page. A token is short-lived by design, and minting is a single request.

Using a Token

Present the secret in the api-key header, in place of your API key:

http
POST /graphql HTTP/1.1
Host: api-gateway.allaboard.eu
Accept: application/graphql-response+json
api-key: aat_your-access-token-here
session: 550e8400-e29b-41d4-a716-446655440000
Content-Type: application/json

{"query": "..."}
POST /graphql HTTP/1.1
Host: api-gateway.allaboard.eu
Accept: application/graphql-response+json
api-key: aat_your-access-token-here
session: 550e8400-e29b-41d4-a716-446655440000
Content-Type: application/json

{"query": "..."}

The session header is required as it is for any other request — see Required Headers.

Every request a token authenticates is attributed to the sales agent and user that minted it, so your order history and audit trail read the same as if you had made the request yourself.

Revoking a Token

A token stops working on its own at expiresAt. To end it sooner, call revokeAccessToken with the token's id — the value returned in the id field, not the secret:

graphql
mutation RevokeAccessToken {
  revokeAccessToken(id: "access_token_02m4y1p1n7c681r781q5w7f7a6") {
    id
    revokedAt
  }
}
mutation RevokeAccessToken {
  revokeAccessToken(id: "access_token_02m4y1p1n7c681r781q5w7f7a6") {
    id
    revokedAt
  }
}

Revoking is idempotent: revoking an already-revoked token succeeds and leaves the original revokedAt alone, so the trail keeps saying when the credential actually stopped working. It is allowed for the sales agent that minted the token and for any agent above it in the agent tree; anything else fails with NOT_AUTHORIZED. An id that names no token fails with NOT_FOUND — which is what you get if you pass the secret here by mistake. The returned token carries token: null, the secret being unreadable here as everywhere else.

AccessToken implements Node, so you can also read a token back with node — using the key that minted it, as a token cannot read itself back — to check its expiresAt and revokedAt. A revokedAt of null does not mean the token still works: an unrevoked token past expiresAt is refused just the same.