Query — Derive a Balance
Derive a running balance from all verified deltas for a customer. Supports checkpointing for efficient pagination.
Use this endpoint to compute a customer's current balance by replaying all verified deltas. For large histories, use checkpoints to resume from a known point instead of replaying from the beginning.
Endpoint
GET https://balance-api.pacspace.io/api/v1/balance/derive/:customerId
Headers
| Header | Required | Description |
|---|---|---|
X-Api-Key | Yes | Your PacSpace API key |
Path Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
customerId | string | Yes | Unique identifier for the customer account |
Query Parameters
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
startingBalance | number | No | 0 | Initial balance to start the derivation from |
startingCheckpoint | string | No | — | Resume derivation from a previous checkpoint |
startingCheckpointType | string | No | itemsRoot | Type of checkpoint: itemsRoot or anchorId |
limit | number | No | 100 | Number of deltas per page (1–1000). Balance is always computed from all deltas. |
offset | number | No | 0 | Number of deltas to skip for pagination. |
Examples
SDK (TypeScript)
import { PacSpace } from '@pacspace-io/sdk';
const pac = new PacSpace({ apiKey: process.env.PACSPACE_API_KEY });
// Simple query — derive from zero
const result = await pac.balance.derive('cust_12345');
console.log(result.computedBalance);
console.log(result.deltasCount);
// With checkpoint — resume from a known point
const next = await pac.balance.derive('cust_12345', {
startingBalance: result.computedBalance,
startingCheckpoint: result.latestReceiptId,
});
Simple Query
Derive a balance from zero, replaying all verified deltas.
cURL
curl -X GET "https://balance-api.pacspace.io/api/v1/balance/derive/cust_12345" \
-H "X-Api-Key: YOUR_API_KEY"
JavaScript (Node.js)
const response = await fetch(
"https://balance-api.pacspace.io/api/v1/balance/derive/cust_12345",
{
headers: {
"X-Api-Key": "YOUR_API_KEY",
},
}
);
const result = await response.json();
console.log(result);
Python
import requests
response = requests.get(
"https://balance-api.pacspace.io/api/v1/balance/derive/cust_12345",
headers={"X-Api-Key": "YOUR_API_KEY"},
)
result = response.json()
print(result)
Query with Checkpoint
Resume from a previous checkpoint to avoid replaying the entire delta history. This is useful for accounts with many transactions.
cURL
curl -X GET "https://balance-api.pacspace.io/api/v1/balance/derive/cust_12345?\
startingBalance=50000&\
startingCheckpoint=0xdef456...&\
startingCheckpointType=itemsRoot" \
-H "X-Api-Key: YOUR_API_KEY"
JavaScript (Node.js)
const params = new URLSearchParams({
startingBalance: "50000",
startingCheckpoint: "0xdef456...",
startingCheckpointType: "itemsRoot",
});
const response = await fetch(
`https://balance-api.pacspace.io/api/v1/balance/derive/cust_12345?${params}`,
{
headers: {
"X-Api-Key": "YOUR_API_KEY",
},
}
);
const result = await response.json();
console.log(result);
Python
import requests
response = requests.get(
"https://balance-api.pacspace.io/api/v1/balance/derive/cust_12345",
headers={"X-Api-Key": "YOUR_API_KEY"},
params={
"startingBalance": 50000,
"startingCheckpoint": "0xdef456...",
"startingCheckpointType": "itemsRoot",
},
)
result = response.json()
print(result)
Response
{
"success": true,
"data": {
"customerId": "cust_12345",
"startingBalance": 0,
"startingCheckpoint": "genesis",
"startingCheckpointType": "itemsRoot",
"computedBalance": 48500,
"deltasCount": 127,
"latestCheckpoint": "0xabc789...",
"latestReceiptId": "0xabc789...",
"deltas": [
{
"anchorId": "a_1234567890",
"itemHash": "0x2d4e7f1a...",
"itemsRoot": "0x8f3a9b2c...",
"receiptId": "0x8f3a9b2c...",
"delta": -1000,
"reason": "Monthly subscription charge",
"referenceId": "inv_98765",
"window": "2026-02",
"declaredTimestamp": "2026-02-10T14:30:00Z",
"blockTimestamp": "2026-02-10T14:30:12Z",
"dataPurged": false,
"verified": true
}
],
"windowSummaries": [
{
"window": "2026-01",
"deltasCount": 42,
"netDelta": 1500,
"firstBlockTimestamp": "2026-01-03T10:15:00Z",
"lastBlockTimestamp": "2026-01-31T22:45:00Z"
}
],
"verificationProof": {
"itemsRoot": "0xabc789...",
"message": "Proof root covers all deltas in this derivation."
}
}
}
Response Fields
| Field | Type | Description |
|---|---|---|
customerId | string | The customer account the balance was derived for |
startingBalance | number | The initial balance used for derivation |
startingCheckpoint | string | Checkpoint the derivation started from ("genesis" if from beginning) |
startingCheckpointType | string | Type of checkpoint used: itemsRoot or anchorId |
computedBalance | number | The derived running balance after replaying all deltas |
deltasCount | number | Total number of verified deltas included in the derivation |
latestCheckpoint | string | null | Checkpoint value you can use in subsequent queries to resume here |
latestReceiptId | string | null | Receipt ID of the most recent delta (same as latestCheckpoint) |
deltas | array | List of individual delta records included in the derivation |
windowSummaries | array | Aggregated summaries grouped by time window |
verificationProof | object | Cryptographic proof that the derivation is correct and untampered |
Delta Object
| Field | Type | Description |
|---|---|---|
anchorId | string | Unique identifier for this delta |
itemHash | string | Content hash of this individual delta |
itemsRoot | string | Proof root covering this delta |
receiptId | string | Receipt identifier (same as itemsRoot) |
delta | number | The adjustment amount |
reason | string | Human-readable reason for the adjustment |
referenceId | string | Your external reference ID, or null if not provided |
window | string | Time window label (e.g., 2026-02) |
declaredTimestamp | string | ISO 8601 timestamp you declared when submitting |
blockTimestamp | string | ISO 8601 timestamp of when verification completed |
dataPurged | boolean | Whether the raw business data has been purged per retention policy |
verified | boolean | Whether the delta has been verified |
Window Summary Object
| Field | Type | Description |
|---|---|---|
window | string | Time window label (e.g., 2026-01) |
deltasCount | number | Number of deltas in the window |
netDelta | number | Net balance change for the window |
firstBlockTimestamp | string | ISO 8601 timestamp of the first delta in the window |
lastBlockTimestamp | string | ISO 8601 timestamp of the last delta in the window |
Verification Proof Object
| Field | Type | Description |
|---|---|---|
itemsRoot | string | Proof root hash covering all deltas in the derivation |
message | string | Human-readable description of the proof |
Pagination
The deltas array in the response is paginated. The pagination object shows the total count and current page:
{
"pagination": {
"total": 5420,
"limit": 100,
"offset": 0
}
}
The computedBalance is always derived from all verified deltas, regardless of pagination. Only the deltas array in the response is paginated — the balance calculation considers every delta.
Scaling with Checkpoints
For customers with large delta counts (1,000+), the response includes a _hint suggesting checkpoint-based derivation. At 50,000+ deltas, a startingCheckpoint is required.
Use latestCheckpoint from a previous derive response as startingCheckpoint for incremental derivation:
# First derivation
GET /api/v1/balance/derive/cust_123
# Subsequent derivation (incremental)
GET /api/v1/balance/derive/cust_123?startingBalance=95000&startingCheckpoint=0xabc...
This keeps response times fast and avoids replaying tens of thousands of deltas on every query. When the _hint is present, it includes the recommended startingCheckpoint value to use.
Using Checkpoints
Checkpoints let you avoid replaying the entire delta history on every query. Here's the recommended workflow:
-
First query — Call without checkpoint parameters. The response includes a
latestCheckpointand thecomputedBalance. -
Store the checkpoint — Save the
latestCheckpointvalue andcomputedBalanceon your side. -
Subsequent queries — Pass
startingBalance(the previously computed balance) andstartingCheckpoint(the stored checkpoint). PacSpace only replays deltas recorded after that checkpoint.
Tip: Combine checkpoints with the Checkpoint endpoint to lock period-end snapshots for billing reconciliation.