Customers and vendors
Two resources, one shape. List, read, create, and pull a statement of account.
Customers and vendors are separate resources rather than one /parties?type= switch, so each maps to exactly one scope. The party type is pinned by the URL and never read from your request — a customers-only key can never reach a vendor.
| Method | Endpoint | Purpose |
|---|---|---|
| GET | /customers | List — page, page_size, search. Scope sales_customers:read |
| POST | /customers | Create — name required. Scope sales_customers:create |
| GET | /customers/{id} | Detail |
| GET | /customers/{id}/statement | Statement of account — startDate, endDate |
/vendors is the same four, on purchases_vendors.
Creating one
curl -X POST https://api.trabalance.com/api/v1/customers \
-H "Authorization: Bearer tk_live_…" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: 8c1f2a7e-9d40-4a21-b0c5-6f2e1d7a4c33" \
-d '{ "name": "Acme Corp", "email": "[email protected]", "currency": "USD",
"paymentTerm": 30, "creditLimit": 25000 }'| Field | Required | Notes |
|---|---|---|
| name | Yes | Legal or trading name, up to 255 characters |
| No | Must be a valid address | |
| phone, address, city, state, country, countryCode | No | countryCode is ISO 3166-1 alpha-2 |
| currency | No | ISO 4217; defaults to the business currency |
| taxId, website, note | No | |
| creditLimit | No | Number, 0 or more |
| paymentTerm | No | Whole days, 0 or more |
| categoryId, centerIds[] | No | Category, and the locations this party is visible in |
Unknown fields are passed through to the same producer the dashboard's form posts to, so anything the form accepts, this accepts. Two fields are stripped whatever you send: id (which would turn the create into an update) and files.
The conflict you will meet
If the party already has a relationship with this business, nothing is created and you get a 409:
{ "error": "conflict",
"error_description": "A customer with this email already exists in your business." }Search first (GET /customers?search=acme) when your side cannot guarantee uniqueness.
Statement of account
curl "https://api.trabalance.com/api/v1/customers/<id>/statement?startDate=2026-01-01&endDate=2026-08-31" \
-H "Authorization: Bearer tk_live_…"The statement is produced by the same ledger producer the app's party page reads, so the closing balance it returns is the balance the customer sees on their statement — not a second calculation that can drift.
Every figure on a party comes from the ledger producer. Do not sum documents on your side and expect the total to match — invoices, credit notes, receipts, opening balances and write-offs all contribute, and the producer is the only thing that knows the whole set.
Related
- Invoices — bill a customer
- Receipts & payments — collect and pay
- Pagination, ids and envelopes
- Permission scopes