Skip to content

Query - Derive A Balance

Derive a customer balance for a scoped window. Defaults to the current UTC month and supports flexible day/month windows.

Use this endpoint to derive a customer balance from verified deltas. If you do not provide scope fields, derive defaults to the current UTC month. You can also derive by period, presets, or custom date ranges.


Endpoint

http
GET https://app.pacspace.io/api/v1/balance/derive/:customerId

Scope Limits

Use the limits endpoint to discover the active backend cap before building scope controls:

http
GET https://app.pacspace.io/api/v1/balance/limits

It returns:

  • maxScopeMonths
  • maxLastNDays
  • maxRetentionDays

Query Parameters

Query parameters

ParameterTypeDescription
startingBalancenumberStarting balance applied before replaying scoped verified deltas. Defaults to 0.
startingCheckpointstringResume from a prior checkpoint using proofRoot or recordId.
startingCheckpointTypestringCheckpoint type. Use proofRoot or recordId.
periodstringScope a single month in YYYY-MM.
timePresetstringPreset scope. Use current_month or custom.
startDatestringCustom scope start as ISO 8601.
endDatestringCustom scope end as ISO 8601.
granularitystringBreakdown granularity: day, week, or month.
limitnumberNumber of rows returned in deltas. Range: 1 to 1000.
offsetnumberOffset for deltas pagination.

Scope Rules

  • Use either checkpoint mode (startingCheckpoint) or scope mode (period / timePreset / startDate + endDate) in one request.
  • Combining checkpoint and scope fields returns 400 INVALID_SCOPE_COMBINATION.
  • Requests beyond the configured scope cap return 400 SCOPE_TOO_WIDE.

SDK Examples

typescript
import { PacSpace } from '@pacspace-io/sdk';

const pac = new PacSpace({ apiKey: process.env.PACSPACE_API_KEY! });

// Default scope: current UTC month
const current = await pac.balance.derive('cust_12345');

// Explicit month scope
const april = await pac.balance.deriveForPeriod('cust_12345', '2026-04');

// Last 12 months helper
const trailing12 = await pac.balance.deriveMonthsBack('cust_12345', 12);

// Custom date window (quick-range chips map to this format)
const trailingWindow = await pac.balance.derive('cust_12345', {
  timePreset: 'custom',
  startDate: '2026-01-01',
  endDate: '2026-03-31',
  granularity: 'day',
});

// Checkpoint mode
const resumed = await pac.balance.derive('cust_12345', {
  startingBalance: current.computedBalance,
  startingCheckpoint: current.latestReceiptId ?? undefined,
});

cURL Example

bash
curl -X GET "https://app.pacspace.io/api/v1/balance/derive/cust_12345?period=2026-04&granularity=day" \
  -H "X-Api-Key: YOUR_API_KEY"

Response Shape (Highlights)

json
{
  "success": true,
  "data": {
    "customerId": "cust_12345",
    "computedBalance": 48500,
    "deltasCount": 127,
    "latestCheckpoint": "chk_9ec7...",
    "latestReceiptId": "chk_9ec7...",
    "scope": {
      "kind": "period",
      "periodId": "2026-04",
      "startDate": "2026-04-01T00:00:00.000Z",
      "endDateExclusive": "2026-05-01T00:00:00.000Z",
      "label": "Apr 2026"
    },
    "granularity": "day",
    "granularBreakdown": [
      {
        "period": "2026-04-01",
        "periodStart": "2026-04-01T00:00:00.000Z",
        "periodEndExclusive": "2026-04-02T00:00:00.000Z",
        "deltaCount": 5,
        "netDelta": -150,
        "runningBalance": 49850
      }
    ]
  }
}

Structured Errors

Derive returns typed errors with actionable hints:

  • INVALID_SCOPE_COMBINATION
  • SCOPE_TOO_WIDE
  • INVALID_PERIOD
  • INVALID_DATE_RANGE
  • INVALID_TIME_PRESET
  • DERIVE_CHECKPOINT_REQUIRED

Example:

json
{
  "message": "Choose either checkpoint mode or scope mode in this request.",
  "code": "INVALID_SCOPE_COMBINATION",
  "hint": "Remove startingCheckpoint or remove period/timePreset/startDate/endDate."
}