Statements

Generate a full account statement for a period, with opening and closing balances per currency.

Before You Start

Read the following guides before proceeding:

GuideWhy
Getting StartedPlatform overview and setup
Api BasicsRequired headers and request configuration
AuthenticationHow to obtain access tokens
Activity HistoryActivity types, directions and subjects

Overview

A statement is a point-in-time document, not a feed page. It covers a fixed period and returns
everything needed to render or export an account statement in one response: the user's identity and
legal address, their bank accounts, opening and closing balances per currency, and every transaction
in the window with its per-operation running balance.

Use the activity feed for browsing and reconciliation. Use this
endpoint when the output is a document — a monthly statement, a tax export, an audit pack.


Generate a Statement

POST /api/v1/activity/statement/full

Request

{
  "start": 1640995200,
  "end": 1672531199,
  "token_addresses": [
    "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
    "0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599"
  ]
}
FieldTypeRequiredDescription
startintegerYesPeriod start, Unix timestamp in seconds. Must be positive
endintegerYesPeriod end, Unix timestamp in seconds. Must be positive and greater than start
token_addressesstring[]NoRestrict the statement to these tokens. Each entry must be a valid address. Omit for all tokens

The period cannot exceed 6 months. A wider range is refused outright — split a year into two
calls rather than retrying.

Response

{
  "owner": "0x742d35Cc6634C0532925a3b8D400631C6D5d1234",
  "user_address": "0x742d35Cc6634C0532925a3b8D400631C6D5d1234",
  "chain_id": 8453,
  "created_at": 1672531200,
  "period": {
    "start": 1640995200,
    "end": 1672531199
  },
  "balances": [
    {
      "currency": "USDC",
      "opening": 1000.50,
      "closing": 1250.75,
      "debit": 500.25,
      "credit": 750.50
    }
  ],
  "user_data": {
    "name": "Alex Gray",
    "legal_address_data": "123 Business Street, Suite 400, New York, NY 10001, USA"
  },
  "user_bank_accounts": {},
  "transactions": [
    {
      "id": "550e8400-e29b-41d4-a716-446655440000",
      "type": "Card",
      "direction": "Outbound",
      "amount": 95.50,
      "currency": "USDC",
      "created_at": 1672531200,
      "updated_at": 1672531200,
      "operations": [
        {
          "hash": "0x1a2b3c4d5e6f7890abcdef1234567890abcdef12",
          "token_address": "0xA0b86a33E6441c58126c96ceb5A7e4E0e9473c1C",
          "account_address": "0x742d35Cc6634C0532925a3b8D400631C6D5d1234",
          "wallet_address": "0x742d35Cc6634C0532925a3b8D400631C6D5d1234",
          "amount": 50.25,
          "token_symbol": "USDC",
          "created_at": 1672531200,
          "resulting_balance": 1050.75
        }
      ]
    }
  ]
}
FieldDescription
ownerOwner address the statement was produced for
user_addressUser's wallet address
chain_idChain the statement covers
created_atWhen the statement was generated (Unix seconds)
period.startPeriod start, echoing the request
period.endPeriod end, echoing the request
balances[].currencyCurrency or token symbol
balances[].openingBalance at period.start
balances[].closingBalance at period.end
balances[].debitTotal debited during the period
balances[].creditTotal credited during the period
user_data.nameStatement holder's name
user_data.legal_address_dataLegal address as a single formatted string
user_bank_accountsThe user's bank accounts, in the same shape as the accounts API
transactions[].idActivity identifier. Matches id in the activity feed
transactions[].typeActivity type — see Activity Types
transactions[].directionInbound or Outbound
transactions[].amountTransaction amount
transactions[].currencyTransaction currency
transactions[].created_atCreation time (Unix seconds)
transactions[].updated_atLast update time (Unix seconds)
transactions[].sourceCounterparty the funds came from. Omitted when not applicable
transactions[].destinationCounterparty the funds went to. Omitted when not applicable
transactions[].operations[].hashOn-chain transaction hash for the operation
transactions[].operations[].token_addressToken contract address
transactions[].operations[].account_addressAccount the operation moved value on
transactions[].operations[].wallet_addressWallet the operation belongs to
transactions[].operations[].amountOperation amount
transactions[].operations[].token_symbolToken symbol
transactions[].operations[].created_atOperation time (Unix seconds)
transactions[].operations[].resulting_balanceRunning balance after this operation

resulting_balance is what makes this a statement rather than a list — it is the balance after the
operation, so a rendered statement needs no client-side accumulation.


Code Examples

const statement = await fetch(`${baseUrl}/api/v1/activity/statement/full`, {
  method: 'POST',
  headers: {
    'Authorization': `Bearer ${accessToken}`,
    'X-User-Wallet': userEoaAddress,
    'X-Chain-Id': chainId,
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    start: 1640995200,
    end: 1672531199
  })
}).then(r => r.json());
statement = requests.post(
    f"{base_url}/api/v1/activity/statement/full",
    headers={
        "Authorization": f"Bearer {access_token}",
        "X-User-Wallet": user_eoa_address,
        "X-Chain-Id": chain_id,
        "Content-Type": "application/json"
    },
    json={"start": 1640995200, "end": 1672531199}
).json()
body, _ := json.Marshal(map[string]int64{
    "start": 1640995200,
    "end":   1672531199,
})

req, _ := http.NewRequest("POST", baseURL+"/api/v1/activity/statement/full", bytes.NewReader(body))
req.Header.Set("Authorization", "Bearer "+accessToken)
req.Header.Set("X-User-Wallet", userEoaAddress)
req.Header.Set("X-Chain-Id", chainId)
req.Header.Set("Content-Type", "application/json")

resp, _ := http.DefaultClient.Do(req)
defer resp.Body.Close()

var statement ActivityFullStatementResponse
json.NewDecoder(resp.Body).Decode(&statement)

Limitations

  • 6-month maximum period. Longer ranges are rejected at validation. Split them client-side.
  • Not paginated. The full transaction set for the period is returned in one response, so a busy
    account over a long window produces a large payload.
  • Timestamps are Unix seconds, not the ISO 8601 strings used elsewhere in the API.
  • token_addresses filters, it does not aggregate. Excluded tokens are absent from both
    transactions and balances, so a filtered statement does not reconcile to the account total.

Error Handling

Validation Errors (400)

Error DetailsDescriptionResolution
start: Start time must be a positive Unix timestampMissing, zero or negativeSend a positive timestamp in seconds
end: End time must be a positive Unix timestampMissing, zero or negativeSend a positive timestamp in seconds
start: Start time must be less than end timeRange inverted or emptyOrder the bounds correctly
end: End time must be within 6 months from start timePeriod too wideSplit into ranges of 6 months or less
token_addresses: each token address must be a valid addressAn entry is not a valid addressSend valid contract addresses

Each error also carries field and issue details — issue values here are invalid_value,
invalid_range, range_exceeds_6_months and invalid_format.

Example Error Response

{
  "error_reason": "ErrorInvalidField",
  "error_description": "Request failed validation",
  "error_category": {
    "category": "CategoryValidationFailure",
    "http_status_code": 400
  },
  "error_details": [
    { "key": "field", "details": "end" },
    { "key": "issue", "details": "range_exceeds_6_months" },
    { "key": "end", "details": "End time must be within 6 months from start time" }
  ]
}

Did this page help you?