Skip to guide

Getting started

Authenticate once, make a first request, and keep the API key away from the browser bundle.

Start with one request

Follow these 3 steps before using the full API reference.

  1. We review every request manually and email approved keys with api:access.
  2. Make one requestKeep the key in a server-side runtime and call /v1/items.
  3. Verify the resultConfirm that the response contains the item data you requested.

Authentication

Every /v1 endpoint needs an API key with api:access. Request access through this form. We review requests manually and email approved keys. Health checks are public; data routes are not.

Required header for data routes
HeaderValue
X-API-Key<your api key>
HTTP requestScroll horizontally if needed
GET /v1/items HTTP/1.1
Host: tboi-api.pabloviniegra.dev
X-API-Key: sk_live_...
X-Request-ID: 7c9e2f5e-1b3d-4f8a-9b6e-2c0a4f7d8e9b
Accept: application/json

Make the first request

Start with the list endpoint. This example runs in a server route and requests 20 items.

  1. Store the key in your server runtime environment.
  2. Call Platinum Gold from that server route.
  3. Return only the data your browser needs.
Server-side TypeScriptScroll horizontally if needed
const API_BASE = "https://tboi-api.pabloviniegra.dev";
const API_KEY = process.env.PLATINUM_GOLD_API_KEY;

export async function getItems() {
  if (!API_KEY) {
    throw new Error("PLATINUM_GOLD_API_KEY is not configured.");
  }

  const response = await fetch(
    `${API_BASE}/v1/items?limit=20`,
    {
      headers: {
        Accept: "application/json",
        "X-API-Key": API_KEY,
      },
    },
  );

  if (!response.ok) {
    throw new Error("Unable to load items.");
  }

  return response.json();
}

Keep this module out of the client bundle. The browser can call your own /api/items route, but it must never receive the API key.

Add request IDs, typed response models, logging, and user-facing error handling after the first call works. The later sections cover those production concerns.

Read the response

A successful list response includes the items and its pagination context. Field names are camelCase on the wire.

Successful responseScroll horizontally if needed
{
  "items": [
    {
      "gameId": 1,
      "name": "The Sad Onion",
      "imageUrl": "https://.../sad_onion.png"
    }
  ],
  "total": 732,
  "limit": 20,
  "offset": 0
}
Continue with the full reference

Reference

Once the first request works, use these sections for the rest of the API contract.

Understand the data

An ItemResponse uses stable camelCase fields. Nullable fields are returned as null when the dataset has no value.

ItemResponse fields
FieldTypeNotes
gameIdintegerStable identifier across syncs
namestringDisplay name
descriptionstringFlavor text or effect description
qualityinteger or null0 through 4; null when unspecified
typestring or nullactive, passive, or familiar
rechargeTimestring or nullFree text such as 12 charges
imageUrlstringAbsolute URL; load images lazily
introducedInVersionstring or nullGame version that introduced the item
Dataset metadataScroll horizontally if needed
{
  "apiVersion": "0.1.0",
  "datasetVersion": "rebirth-2025-08",
  "gameVersion": "Repentance+",
  "lastSync": "2025-08-20T10:15:00Z",
  "items": 732
}

Know the endpoints

Health checks do not need a key. Every /v1 route does, and all responses are JSON.

Available API routes
MethodPathAuthPurpose
GET/healthNoneLiveness probe
GET/health/readyNonePostgreSQL and Redis readiness
GET/v1/itemsX-API-KeyPaginated, filterable item list
GET/v1/items/{gameId}X-API-KeyOne item by stable gameId
GET/v1/items/randomX-API-KeyOne random item honoring filters
GET/v1/metaX-API-KeyDataset metadata and last sync

Health checks

/health returns 200 with { "status": "ok" } when the process is up. It is safe to use as a liveness probe. /health/ready returns 200 when PostgreSQL and Redis are reachable, or 503 when the service is degraded.

Filter the item list

All list filters are optional. Combine them in the query string, and cache each complete URL separately.

Query parameters for /v1/items
ParameterTypeDefaultNotes
searchstringNoneCase-insensitive item name match
qualityintegerNone0 through 4
typestringNoneactive, passive, or familiar
versionstringNoneExact introducedInVersion match
sortenumnamename, quality, or game_id
orderenumascasc or desc
limitinteger201 through 100
offsetinteger0Zero or greater

The random endpoint accepts only search, quality, type, and version. It does not accept pagination or sorting parameters.

Handle errors

Errors use one JSON shape. Show a useful recovery message in your UI and keep the raw response in your server-side error tracker.

Error responseScroll horizontally if needed
{ "error": { "code": "INVALID_API_KEY", "message": "Invalid API key" } }
Common HTTP errors
HTTPWhenRecovery
401Header missing or key invalidCheck the server-side credential and header name
403Key lacks api:accessRequest a key with the required scope
404gameId does not existCheck the stable identifier
422Query value has the wrong type or rangeValidate filters before sending the request
503PostgreSQL or Redis is unavailableRetry with backoff and show service status

Trace a request

Every response includes X-Request-ID. Send your own ID when possible; otherwise the API generates one. Forward it to your logs and support tickets.

Request correlation headerScroll horizontally if needed
X-Request-ID: 7c9e2f5e-1b3d-4f8a-9b6e-2c0a4f7d8e9b

Cache responses

Cache at your client boundary using the full query string when the route is safe to reuse. Health checks are never a cache hot path.

Client caching recommendations
RouteServer TTLClient recommendation
/v1/items15 minCache by the complete query string
/v1/items/{gameId}24 hCache by stable gameId
/v1/meta24 hCache for the session; refresh on user action
/v1/items/randomNoneCache yourself only if you reuse the result
/health/*NoneDo not cache

Plan for change

  • /v1 remains available until a new major version is announced.
  • New response fields are additive; do not fail on unknown fields.
  • Removing or renaming a field requires a major version.
  • Load item images lazily and treat imageUrl as an absolute URL.

Find the reference

Use the interactive reference for exploratory requests. Include the X-Request-ID from a failed call when asking for help.