Credit accounts
Everything here needs credit:read. Check what you hold with GET /v1/me.
| Endpoint | Returns |
|---|---|
GET /v1/credit-accounts |
A page of allotments, filterable by siteId, divisionId, userId, active |
GET /v1/credit-accounts/{creditAccountId} |
One allotment and its remaining balance |
GET /v1/credit-accounts/{creditAccountId}/adjustments |
That account’s ledger - every debit and credit, with the order that caused it |
Read-only. Credit is allotted by staff tooling and drawn down by the order flow. There is no
credit:write scope, and no endpoint here creates or adjusts credit.
Its own scope, not orders:read. Balances are financial standing, and a partner running an
order-status integration should not receive their customers’ remaining credit as a side effect of a
scope they asked for to poll shipments.
Read this first
Section titled “Read this first”Two behaviors that are not obvious from the endpoint list, and that are much cheaper to learn here than from a reconciliation that does not balance.
Whose credit it is
Section titled “Whose credit it is”An account belongs to either a division or a user - exactly one of divisionId and userId is
set on every account, and the other is null. They are published as two fields rather than one
polymorphic holder so that a row which ever violated that is visible as such rather than silently
attributed to the wrong party.
Both kinds come back by default. Narrow with ?divisionId= or ?userId=, or with ?siteId=
for one granted site - GET /v1/credit-accounts?siteId=222 and
GET /v1/sites/222/credit-accounts are the same request, same handler, same result. Use
whichever reads better in your code; a siteId outside your grant is a 400 invalid_site_id
either way.
# One division's allotments, live ones onlycurl -s -H "Authorization: Bearer $TOKEN" \ "https://api.partners.collaterate.com/v1/credit-accounts?divisionId=4021&active=true"Passing both filters is accepted and returns an empty page rather than an error: the two are mutually exclusive on every row, so the honest answer to “held by division 5 and user 9” is that there are none.
active must be exactly true or false. 1, yes and on are rejected rather than coerced,
because every coercion rule anyone might expect disagrees with some other one about 0.
Inactive accounts are listed
Section titled “Inactive accounts are listed”An expired or deactivated allotment stays in the list with active: false, rather than
disappearing. Hiding it would make “inactive” and “never existed” look identical - the same
decision users and divisions make. Pass ?active=true when you only want live ones.
The ledger
Section titled “The ledger”Each adjustment is one movement of money and the order that caused it:
{ "amount": "-42.1700000000", "type": "PRODUCT_DEBIT", "orderNumber": 550123, "postedOn": "2026-02-11T14:22:03.000Z"}type is a raw movement code, and the set is open. PRODUCT_DEBIT, TAX_DEBIT,
SHIPPING_DEBIT, ORDER_HANDLING_DEBIT, ORDER_ITEM_HANDLING_DEBIT and their _CREDIT reversals
are the ten values in use today, but there is no enumeration behind them upstream and nothing stops
an eleventh appearing.
Match on the _DEBIT/_CREDIT suffix rather than enumerating the ten. Filtering with
?type= accepts any well-formed upper-case code - an unknown one returns an empty page rather than
an error, so a new code does not break your integration on the day it ships.
Resolve orderNumber with GET /v1/orders/{orderNumber}.
Pagination
Section titled “Pagination”All three list endpoints use the same cursor/limit contract as every other collection here:
walk nextCursor until it is null. Default page size 50, capped at 200.
Errors
Section titled “Errors”See Errors for the full table. The ones specific to this surface:
code |
Status | Meaning |
|---|---|---|
invalid_credit_account_id |
400 | Path segment is not a positive whole number of at most nine digits |
invalid_site_id |
400 | The siteId filter is malformed, or names a site outside your grant |
invalid_division_id · invalid_user_id |
400 | The filter is not a positive whole number |
invalid_active |
400 | active was something other than exactly true or false |
invalid_adjustment_type |
400 | type is not an upper-case movement code |
invalid_cursor |
400 | The cursor could not be decoded - restart pagination without one |
credit_account_not_found |
404 | No such account on your granted sites |
An account that does not exist and one that sits on a site you were not granted return the
identical 404, on purpose - see Tenancy and access.
Asking for the adjustments of an account you cannot see is that same 404, not an empty page.