Quickstart

Create your first API key in the Owner Dashboard, hit the BetterSuite GraphQL endpoint, and parse a response.

Last updated May 19, 2026

This is the shortest path from "I have a BetterSuite tenant" to "my server is talking to BetterSuite over GraphQL." Conceptual depth lives in Authentication — this page is a checklist.

Prerequisites

  • An active BetterSuite tenant.
  • Tenant Owner access to the Owner Dashboard. API key creation is Owner-tier — a regular Tenant Admin cannot issue or rotate keys.
  • A terminal with curl and jq, or any HTTP client.

Step 1: Create an API key

  1. Sign in to bettersuite.io/dashboard.
  2. Open API Keys from the sidebar (one of the flat sidebar items in the Owner Dashboard).
  3. Click Create Key, give it a name (e.g. dev-laptop), and optionally set Rate limit (req/min) and Rate limit (req/day). Leave both blank to inherit the tenant default — see Rate Limits.
  4. Copy the key from the amber banner that appears. We show the plaintext exactly once; the database only stores the SHA-256 hash. If you lose it, rotate it.

The key looks like this:

btk_019234ab_Kj8mN2pQrStUvWxYz1a2B3c4D5e6F7g8H9i0...
  • btk_ — fixed prefix for a BetterSuite tenant key.
  • 019234ab — first 8 characters of your tenant's UUID, helpful when grepping logs.
  • The rest is 32 random bytes, base64url-encoded.

The dashboard lists every key by its key_prefix (first 12 chars), creation time, last used time, and rate-limit overrides. Active keys can be rotated (a step-up password prompt; old key revoked, new one issued) or revoked.

Step 2: Hit the endpoint

The production endpoint:

POST https://api.bettersuite.io/graphql

Send the key in the X-Api-Key header — not Authorization: Bearer. The Authorization header is reserved for user-bound JWT sessions.

Step 3: Send your first request

A simple query — tenantInfo returns your tenant's display name, currency, status, plan, and branding. It's a good handshake call because it needs only the API key for authentication.

cURL

curl https://api.bettersuite.io/graphql \
  -H "X-Api-Key: $BETTERSUITE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"query": "{ tenantInfo { id name baseCurrency status } }"}' | jq

JavaScript

const res = await fetch("https://api.bettersuite.io/graphql", {
  method: "POST",
  headers: {
    "X-Api-Key": process.env.BETTERSUITE_API_KEY,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    query: "{ tenantInfo { id name baseCurrency status } }",
  }),
});
console.log(await res.json());

Python

import os, requests

res = requests.post(
    "https://api.bettersuite.io/graphql",
    headers={"X-Api-Key": os.environ["BETTERSUITE_API_KEY"]},
    json={"query": "{ tenantInfo { id name baseCurrency status } }"},
)
print(res.json())

A successful response looks like:

{
  "data": {
    "tenantInfo": {
      "id": "01923a4b-...",
      "name": "Acme Rides",
      "baseCurrency": "USD",
      "status": "ACTIVE"
    }
  }
}

If data is null and errors is populated, jump to the next section.

Step 4: Browse the schema

You can introspect via the standard __schema query, but it returns ~1.5 MB. The structured reference at GraphQL API is generated from the same schema.graphql and is grouped by subgraph (identity, tenant, taxi, shop, parking, payment, payout, etc. — 21 subgraphs in total).

Common errors

The auth middleware returns HTTP-level failures (the request never reaches the GraphQL handler):

HTTPMessageCause
401Invalid API key formatKey doesn't start with btk_ or is shorter than 12 chars
401Unknown API keyKey's hash isn't in the database — probably a typo or a key from another environment
401API key is revoked or expiredKey exists but was revoked, or its expires_at is in the past
401Invalid or expired tokenSent on the Authorization: Bearer header path — likely a malformed JWT

GraphQL-level errors (HTTP 200 with errors populated) carry a structured code in extensions.code. Common identity codes include UNAUTHORIZED, TENANT_NOT_FOUND, INVALID_CREDENTIALS, INVALID_REFRESH_TOKEN, SESSION_REVOKED, SESSION_EXPIRED, STEP_UP_REQUIRED, PERMISSION_DENIED, and VALIDATION_ERROR.

What's next

  • API Keys — rotation, revocation, storage discipline.
  • JWT Sessions — for user-bound calls from a mobile or web app.
  • RequestContext — what the backend resolves about each call.
  • Rate Limits — what counts and how to back off.

Build the foundation once. Expand without limits.

BetterSuite is built for teams who see on-demand as a business — not a feature.