Authentication

Every request to /api/v1/* must carry a bearer token. The token is a signed JWT (HS256) whose sub claim is the user id and whose tier claim drives tier-gated endpoints.

bash
curl https://api.closeline.io/v1/games/today \
  -H "Authorization: Bearer $CLOSELINE_API_KEY"

The API also accepts the same-origin cl_sess cookie for the web UI's own requests — third-party clients should always use the Authorization header.

#Obtaining a token

Sign up at /signup and generate a key from the account dashboard. Each key is bound to a single user and inherits that user's tier. Rotating your key invalidates the old one immediately.

#Token lifetime

  • Access TTL: 86,400 seconds (24 hours) by default. Configurable server-side via JWT_ACCESS_TTL_SECONDS.
  • Issuer: closeline.io (overridable via JWT_ISSUER).
  • No refresh token at v1 — clients re-authenticate after expiry. Coarse revocation is done by rotating JWT_SECRET on the server.

#From the SDK

ts
import { Closeline } from "@closeline/sdk";

// Explicit — required in serverless envs where process.env is scrubbed.
const cl = new Closeline({ apiKey: process.env.CLOSELINE_API_KEY! });

// Or, rely on the env default:
//   new Closeline()   // reads process.env.CLOSELINE_API_KEY

#Responses

  • 401 unauthorized — missing, malformed, or expired token. Body carries { error: { code: "unauthorized", ... } }.
  • 403 tier_insufficient — valid token, but your tier doesn't cover the endpoint. See Errors.

#Every response carries

  • x-request-id — opaque uuid for support / tracing.
  • x-ratelimit-limit / x-ratelimit-remaining / x-ratelimit-reset — per-tier rate-limit hints.