Skip to main content
All endpoints below are GET and cost zero credits. Authentication is the same as every other scanner call (Authorization: Bearer <psk_*> or <JWT>). The TypeScript SDK exposes each one as a typed method — see the SDK reference.

GET /v1/scanner/credits/balance

Authoritative current balance plus lifetime totals.
curl -H "Authorization: Bearer $SCANNER_KEY" \
  https://scanner.getsly.ai/v1/scanner/credits/balance
{
  "balance": 96,
  "grantedTotal": 100,
  "consumedTotal": 4
}
FieldNotes
balanceCurrent spendable credits.
grantedTotalLifetime sum of grant-reason rows in the ledger.
consumedTotalLifetime sum of consume rows minus refund rows (net of auto-refunds on 4xx/5xx).
For most integrations you don’t need to call this directly — every billed response includes an X-Credits-Remaining header, and the SDK tracks it automatically.

GET /v1/scanner/credits/activity

Day-bucketed billable scan counts sourced directly from the credit ledger. Use this for usage charts and billing reconciliation — it never undercounts because the ledger is written synchronously inside the credits middleware.
curl -H "Authorization: Bearer $SCANNER_KEY" \
  "https://scanner.getsly.ai/v1/scanner/credits/activity?from=2026-04-01T00:00:00Z"
{
  "data": [
    { "day": "2026-05-02", "scans": 17, "credits": 17 }
  ]
}
Query params:
ParamTypeNotes
fromstringISO-8601 timestamp. Optional — defaults to start of all-time.
tostringISO-8601 timestamp. Optional — defaults to now.
Each day row reports net activity: a refunded validation error is subtracted from scans and credits so the count matches what the partner actually paid for.

GET /v1/scanner/credits/ledger

Per-row ledger of every grant, consume, refund, and adjustment. Paginated, with optional scan-result join.
curl -H "Authorization: Bearer $SCANNER_KEY" \
  "https://scanner.getsly.ai/v1/scanner/credits/ledger?limit=50&page=1&expand=scan"
{
  "data": [
    {
      "id": "1ee1d779-…",
      "delta": -1,
      "reason": "consume",
      "source": "request:2fb64db5-…",
      "balance_after": 82,
      "metadata": {
        "endpoint": "POST /v1/scanner/scan",
        "key_id": "708674e2-…"
      },
      "created_at": "2026-05-02T20:26:33.321799+00:00",
      "scan": {
        "id": "b16d213c-…",
        "request_id": "2fb64db5-…",
        "domain": "reddit.com",
        "readiness_score": 15,
        "scan_status": "completed"
      }
    }
  ],
  "pagination": { "page": 1, "limit": 50, "total": 23, "totalPages": 1 }
}
Query params:
ParamTypeNotes
fromstringISO-8601 timestamp. Optional.
tostringISO-8601 timestamp. Optional.
limitinteger1–500. Default 100.
pageinteger1-based. Default 1. (Legacy ?offset=N also accepted.)
expandstringComma-separated list. Currently only scan is supported — joins consume rows to their merchant_scans row via request_id.
Row fields:
FieldNotes
deltaSigned integer. Negative for consume, positive for grant/refund.
reasongrant | consume | refund | adjustment.
sourceFor consumes: "request:<uuid>". For grants: invoice id, pack id, or free-form. For refunds: "refund:<uuid>" referencing the original consume’s request_id.
metadata.endpointWhich API call caused the consume (e.g. POST /v1/scanner/scan).
metadata.key_idWhich scanner key was used.
metadata.status_code (refunds)The HTTP status that triggered the refund.
metadata.reason (refunds)"client_error" (4xx) or "server_error" (5xx).
scan (with expand=scan)Joined merchant_scans summary. Present only on consume rows whose request_id matches a scan.

Audit-trail use case

expand=scan answers “what did I get for this charge?” without a second call. Pre-fix consumes (before the request_id join shipped on 2026-05-02) won’t have the scan field — the row will just show source as before.

GET /v1/scanner/usage

Aggregated request counts and credit consumption, grouped by endpoint or day. Aggregation runs server-side (no row caps).
curl -H "Authorization: Bearer $SCANNER_KEY" \
  "https://scanner.getsly.ai/v1/scanner/usage?group_by=endpoint"
Query params:
ParamTypeNotes
group_bystringendpoint (default) or day.
fromstringISO-8601. Optional.
tostringISO-8601. Optional.
Endpoint grouping:
{
  "group_by": "endpoint",
  "data": [
    {
      "endpoint": "POST /v1/scanner/scan",
      "requests": 24,
      "credits": 24,
      "errors": 1,
      "total_duration_ms": 91842
    },
    {
      "endpoint": "GET /v1/scanner/credits/balance",
      "requests": 18,
      "credits": 0,
      "errors": 0,
      "total_duration_ms": 2156
    }
  ]
}
Day grouping:
{
  "group_by": "day",
  "data": [
    {
      "day": "2026-05-02",
      "requests": 408,
      "credits": 24,
      "errors": 1,
      "total_duration_ms": 55425
    }
  ]
}
For billable-activity charts, prefer /credits/activity — it sources from the ledger and is never affected by best-effort telemetry. /usage is the right call when you also want read traffic + per-endpoint latency breakdowns.