REST API · v1

API Documentation

Three endpoints. Bearer-token auth. JSON in, JSON out. Built for high-volume gaming platforms with HMAC-hashed codes, AES-256-GCM vault encryption, and scope-based authorization.

SHA-256 hashed codes
AES-256-GCM vault
Edge-deployed
JSON / HTTPS

1. Getting started

  1. Open the dashboard and sign in.
  2. Go to API Keys and create a key for your platform. Copy the gck_live_… token — it is only shown once.
  3. Generate or import a batch of cards in Generate. Store the redemption codes from the Vault page.
  4. Call the endpoints below with your bearer token.

2. Authentication

All requests must include your API key in one of two headers. Keys are hashed with SHA-256 at rest — we cannot recover lost keys, you must rotate them.

# Option A — Authorization header (recommended)
Authorization: Bearer gck_live_xxxxxxxxxxxxxxxxxxxx

# Option B — x-api-key header
x-api-key: gck_live_xxxxxxxxxxxxxxxxxxxx
Never expose keys client-side. All endpoints must be called from your server. A leaked issue-scoped key allows minting new cards.

3. Base URL & format

All endpoints use HTTPS and accept/return application/json.

Base URL:  https://your-app.lovable.app
Method:    POST
Headers:   Content-Type: application/json
           Authorization: Bearer gck_live_...
CORS:      * (preflight OPTIONS supported)

4. Scopes

Each API key has a list of allowed scopes. A request with a missing scope returns 403. Assign the minimum scope your platform needs.

balance

Read card balance and status.

redeem

Deduct from a card during checkout.

issue

Mint new cards on demand (high trust).

5. Endpoints

POST
/api/public/v1/cards/balance
scope: balance

Check Card Balance

Look up the current balance, denomination, and status of a card by its redemption code. Read-only.

Request body

{
  "code": "ABCD-EFGH-JKLM-NPQR"
}

Success response (200)

{
  "serial_number": "GC-XXXX-XXXX-XXXX",
  "denomination": 100,
  "balance": 75.50,
  "status": "active",
  "currency": "USD"
}

Example (curl)

curl -X POST https://your-app.lovable.app/api/public/v1/cards/balance \
  -H "Authorization: Bearer gck_live_..." \
  -H "Content-Type: application/json" \
  -d '{ "code": "ABCD-EFGH-JKLM-NPQR" }'

Error responses

  • 400Invalid input
  • 401Missing or invalid API key
  • 403Missing scope: balance
  • 404Card not found
POST
/api/public/v1/cards/redeem
scope: redeem

Redeem (Deduct) Balance

Deduct an amount from a card. Uses optimistic locking to prevent double-spend under concurrency.

Request body

{
  "code": "ABCD-EFGH-JKLM-NPQR",
  "amount": 25.00,
  "reference": "order_12345"
}

Success response (200)

{
  "serial_number": "GC-XXXX-XXXX-XXXX",
  "amount_deducted": 25.00,
  "balance": 50.50,
  "status": "active",
  "currency": "USD"
}

Example (curl)

curl -X POST https://your-app.lovable.app/api/public/v1/cards/redeem \
  -H "Authorization: Bearer gck_live_..." \
  -H "Content-Type: application/json" \
  -d '{ "code": "ABCD-EFGH-JKLM-NPQR", "amount": 25.00, "reference": "order_12345" }'

Error responses

  • 400Invalid input
  • 401Missing or invalid API key
  • 402Insufficient balance
  • 403Missing scope: redeem
  • 404Card not found
  • 409Card is depleted/voided/expired
POST
/api/public/v1/cards/issue
scope: issue

Issue New Cards

Generate brand-new cards on demand and assign them to your platform. Returns plaintext codes ONCE.

Request body

{
  "denomination": 100,
  "quantity": 10,
  "reference": "batch_2026_01"
}

Success response (200)

{
  "currency": "USD",
  "denomination": 100,
  "count": 10,
  "cards": [
    { "serial_number": "GC-...", "redemption_code": "....", "balance": 100 }
  ]
}

Example (curl)

curl -X POST https://your-app.lovable.app/api/public/v1/cards/issue \
  -H "Authorization: Bearer gck_live_..." \
  -H "Content-Type: application/json" \
  -d '{ "denomination": 100, "quantity": 10, "reference": "batch_2026_01" }'

Error responses

  • 400Invalid input (denomination must be one of 5/10/20/50/100/200/500/1000)
  • 401Missing or invalid API key
  • 403Missing scope: issue
  • 500Issue failed

6. Error format

All errors return a JSON body with an error field and the appropriate HTTP status.

{
  "error": "Insufficient balance",
  "balance": 12.50
}

7. Security model

  • Codes are never stored in plaintext. Lookups happen via SHA-256 hash. The Vault uses AES-256-GCM with a derived key for recovery exports.
  • API keys are SHA-256 hashed at rest. Only the prefix (gck_live_xxxx) is visible after creation.
  • Optimistic locking on redeem. Concurrent redeems can't double-spend — the balance update is atomic against the previous balance.
  • Row-Level Security enforced in the database — staff/admin scopes for dashboard, service-role only for public APIs.
  • All requests are logged with platform name, IP, endpoint, status, and timestamp for audit.
  • Scope-based authorization — each key only does what it's allowed to do.
  • Edge-deployed with HTTPS-only, CORS preflight, and validated inputs (Zod schemas).

8. Best practices

  • Call our API only from your server — never from a browser or mobile app directly.
  • Use a unique reference per transaction so you can reconcile with your order system.
  • Rotate API keys at least every 90 days, and immediately if exposure is suspected.
  • Use separate keys per environment (staging / production) and per platform.
  • Implement retry-with-backoff but treat redeem as not idempotent — check balance first if uncertain.
  • Monitor the Logs page for unexpected 4xx/5xx spikes.