Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions .stainless/stainless.yml
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,11 @@ resources:
internal_account_update_request: '#/components/schemas/InternalAccountUpdateRequest'
internal_account_export_request: '#/components/schemas/InternalAccountExportRequest'
internal_account_export_response: '#/components/schemas/InternalAccountExportResponse'
# Periodic statements
balance_change: '#/components/schemas/BalanceChange'
balance_change_list_response: '#/components/schemas/BalanceChangeListResponse'
confirm_statement_delivery_request: '#/components/schemas/ConfirmStatementDeliveryRequest'
statement_delivery: '#/components/schemas/StatementDelivery'
# KYC link generation
kyc_link_create_request: '#/components/schemas/KycLinkCreateRequest'
kyc_link_response: '#/components/schemas/KycLinkResponse'
Expand All @@ -143,6 +148,10 @@ resources:
update_internal_account:
endpoint: patch /internal-accounts/{id}
body_param_name: InternalAccountUpdateRequest
list_balance_changes: get /internal-accounts/{id}/balance-changes
confirm_statement_delivery:
endpoint: post /internal-accounts/{id}/statement-confirmations
body_param_name: ConfirmStatementDeliveryRequest
create_kyc_link:
endpoint: post /customers/{customerId}/kyc-link
body_param_name: KycLinkCreateRequest
Expand Down
301 changes: 301 additions & 0 deletions mintlify/openapi.yaml

Large diffs are not rendered by default.

301 changes: 301 additions & 0 deletions openapi.yaml

Large diffs are not rendered by default.

2 changes: 2 additions & 0 deletions openapi/components/schemas/errors/Error409.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ properties:
| CARD_NOT_MUTABLE | The card is `CLOSED`, so it can no longer be mutated |
| CARD_LIMIT_REACHED | The platform has reached the maximum number of live cards it may hold, or the cardholder already holds a card and the platform is limited to one per cardholder. Closing a card frees its slot; contact Lightspark to raise the limit |
| STABLECOIN_GRID_ENABLEMENT_NOT_REQUESTABLE | Grid enablement can only be requested while the stablecoin is `NOT_ENABLED` (a repeat request while already `PENDING_APPROVAL` succeeds). `ENABLING`, `ENABLED` and `DISABLED` are driven by Lightspark and cannot be requested |
| NOT_YET_AVAILABLE | The request is valid, but its result is not available yet because the data it depends on could still change. Retry later. `reason` says what is outstanding. For balance changes, card settlement for a window boundary has not closed |
| CONFLICT | Generic resource-state conflict. Returned, for example, when `platformCustomerId` on a customer create call collides with an existing active customer on the same platform |
| DOCUMENT_ALREADY_EXISTS | A document of this type already exists for the holder; replace it with PUT |
| DUPLICATE_EXTERNAL_ACCOUNT | An equivalent external account already exists |
Expand All @@ -46,6 +47,7 @@ properties:
- CARD_NOT_MUTABLE
- CARD_LIMIT_REACHED
- STABLECOIN_GRID_ENABLEMENT_NOT_REQUESTABLE
- NOT_YET_AVAILABLE
- CONFLICT
- DOCUMENT_ALREADY_EXISTS
- DUPLICATE_EXTERNAL_ACCOUNT
Expand Down
32 changes: 32 additions & 0 deletions openapi/components/schemas/internal_accounts/BalanceChange.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
type: object
description: >-
One movement of the account's balance, signed in the account holder's
polarity: money out is negative and money in is positive, so a window's
changes sum to its closing balance less its opening balance.
required:
- id
- transactionId
- amount
- effectiveAt
properties:
id:
type: string
description: Stable identifier for this balance change
example: BalanceChange:019542f5-b3e7-1d02-0000-000000000003
transactionId:
type: string
description: >-
Opaque identifier for the movement this change belongs to. Several
changes can share one, so it groups the lines of a single movement on a
statement. It is not a `Transaction` id and does not resolve through
`GET /transactions/{transactionId}`.
example: 019542f5-b3e7-1d02-0000-000000000004
amount:
$ref: ../common/CurrencyAmount.yaml
effectiveAt:
type: string
format: date-time
description: >-
When the account holder's balance moved. Changes are ordered by this
time.
example: '2026-09-03T14:31:00Z'
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
type: object
description: >-
A window of balance changes with the balances that bound it. The opening and
closing balances describe the whole window, not the page, so they are the
same on every page, and the identity `openingBalance + Σ(data[].amount) ==
closingBalance` holds only once every page's `data` is summed.
required:
- data
- periodStart
- periodEnd
- openingBalance
- closingBalance
- hasMore
properties:
data:
type: array
description: Balance changes on this page, ordered by `effectiveAt`
items:
$ref: ./BalanceChange.yaml
periodStart:
type: string
format: date-time
description: Start of the window, inclusive
example: '2026-08-01T00:00:00-05:00'
periodEnd:
type: string
format: date-time
description: End of the window, exclusive
example: '2026-09-01T00:00:00-05:00'
openingBalance:
$ref: ../common/CurrencyAmount.yaml
closingBalance:
$ref: ../common/CurrencyAmount.yaml
hasMore:
type: boolean
description: Indicates if more changes are available beyond this page
example: false
nextCursor:
type: string
description: >-
Cursor to retrieve the next page of results (only present if hasMore is
true)
example: BalanceChange:019542f5-b3e7-1d02-0000-000000000003
countIsExact:
type: boolean
description: Whether `totalCount` is exact rather than capped
example: true
totalCount:
type: integer
description: Number of balance changes in the window, across all pages
example: 42
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
type: object
required:
- periodStart
properties:
periodStart:
type: string
format: date
description: >-
First day of the statement period being confirmed, a calendar month in
US Central time. Must be the first day of a month that has already
begun.
example: '2026-09-01'
deliveredAt:
type: string
format: date-time
description: >-
When the statement was delivered to the customer. Must include a
timezone offset, must not be in the future, and must be at or after the
end of the period. Defaults to the current time.
example: '2026-10-03T14:31:00Z'
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
type: object
required:
- internalAccountId
- periodStart
properties:
internalAccountId:
type: string
description: The account whose statement this is
example: InternalAccount:019542f5-b3e7-1d02-0000-000000000002
periodStart:
type: string
format: date
description: First day of the statement period
example: '2026-09-01'
fetchedAt:
anyOf:
- type: string
format: date-time
- type: 'null'
description: >-
When the statement for this period was first read from Grid, or null if
it never has been
example: '2026-10-01T09:00:00Z'
confirmedAt:
anyOf:
- type: string
format: date-time
- type: 'null'
description: >-
When the statement was first delivered to the customer, or null if
delivery has not been confirmed. Later confirmations do not move it.
example: '2026-10-03T14:31:00Z'
31 changes: 31 additions & 0 deletions openapi/openapi.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
parameters:
- name: id
in: path
description: The id of the internal account to list balance changes for.
required: true
schema:
type: string
example: InternalAccount:019542f5-b3e7-1d02-0000-000000000002

get:
summary: List balance changes for a period
description: >
Every change to this account's balance in a window, in the order the money
moved, with the opening and closing balances for that window in the same
response.


This is the statement feed. `GET /transactions` returns one row per
transaction. This returns one row per change to the balance, and a
transaction that moves the balance more than once produces more than one
change: an ACH deposit and its later return are two, and a card purchase
that clears in two parts is two.


**The identity to assert:** `openingBalance + Σ(data[].amount) ==
closingBalance`, summed over every page. The opening and closing balances
describe the window rather than the page, so they are the same on every
page. Page until `hasMore` is false, then assert the identity before
rendering a statement.


`from` and `to` are instants and the window is half-open: a change at
exactly `to` belongs to the next window. Consecutive periods therefore
tile with no gap and no overlap. For a monthly statement, pass the first
instant of the month and the first instant of the following month, both
in US Central time (`America/Chicago`). Grid records a statement as
fetched only for a window that is exactly one such month.


A window whose card settlement has not closed is refused with `409
NOT_YET_AVAILABLE`, because its figures could still change. Retry once
it has settled.


Merchant, counterparty and rail detail live on the transaction; read them
from `GET /transactions`.
operationId: listInternalAccountBalanceChanges
tags:
- Periodic Statements
security:
- BasicAuth: []
parameters:
- name: from
in: query
required: true
description: Start of the window, inclusive. Must include a timezone offset.
schema:
type: string
format: date-time
example: '2026-08-01T00:00:00-05:00'
- name: to
in: query
required: true
description: >-
End of the window, exclusive. Must include a timezone offset and must
not be in the future.
schema:
type: string
format: date-time
example: '2026-09-01T00:00:00-05:00'
- name: limit
in: query
required: false
description: Maximum number of changes to return per page
schema:
type: integer
minimum: 1
maximum: 200
default: 100
- name: cursor
in: query
required: false
description: Cursor for pagination (returned from previous request)
schema:
type: string
responses:
'200':
description: The balance changes in the window, with the balances that bound it
content:
application/json:
schema:
$ref: ../../components/schemas/internal_accounts/BalanceChangeListResponse.yaml
'400':
description: >-
Bad request. Returned when `from` or `to` is missing, has no timezone
offset, or is in the future, when `from` is not before `to`, when
`cursor` was not issued by this endpoint, or when the account has no
statement of its own.
content:
application/json:
schema:
$ref: ../../components/schemas/errors/Error400.yaml
'401':
description: Unauthorized
content:
application/json:
schema:
$ref: ../../components/schemas/errors/Error401.yaml
'404':
description: Internal account not found
content:
application/json:
schema:
$ref: ../../components/schemas/errors/Error404.yaml
'409':
description: >-
The window is not final yet. Card settlement for one of its boundaries
has not closed, so its balances and changes could still change. Retry
once it has settled.
content:
application/json:
schema:
$ref: ../../components/schemas/errors/Error409.yaml
'500':
description: Internal service error
content:
application/json:
schema:
$ref: ../../components/schemas/errors/Error500.yaml
Loading
Loading