API reference
Read your commission data from your own tools
A read-only HTTP API over everything PayoutEngine calculates. Point your warehouse, your BI tool or a twenty-line script at it and pull payouts straight into your own reporting.
- Base URL
- /api/v1
- OpenAPI document
-
/api/v1/openapi.json
The full machine-readable description, for generating a client.
Authorization
Create a key in the app under Settings, then API keys. It is shown once. Send it on every request:
curl https://www.payoutengine.io/api/v1/payouts \
-H "Authorization: Bearer pe_live_YOUR_KEY"
Keys belong to an organization, not to a person, and they are read-only. A key can never change a number.
Money is a string
Every money value comes back as a decimal string, for example "4987.50", never as a JSON number. A JSON number is a double in most parsers, and a double cannot hold every cent exactly. Parse these into your own decimal type.
{ "net_amount": "4987.50", "currency": "USD" }
Paging
Lists are paged by cursor, not by page number, so a payout run that finishes while you are paging never makes you skip a record. Read next_cursor from each response and send it back as starting_after until has_more is false.
{ "data": [ ... ], "has_more": true, "next_cursor": "payout_9d4f2a" }
Errors
Every refusal has the same shape, so one branch handles all of them.
{ "error": { "code": "unauthorized", "message": "No valid API key. ..." } }
| Status | Meaning |
|---|---|
| 401 | The Authorization header is missing, malformed, or names a key that has been revoked. |
| 403 | The key is valid but is not permitted to read. Keys grant read access only. |
| 404 | No record with that id is readable by this key. |
| 400 | The starting_after value does not name a record this key can read. |
| 429 | This key has made too many requests. Retry after the window. |
Endpoints
| Method | Path |
|---|---|
| GET |
/api/v1/reps List reps Every sales rep at this organization, including those who have left, so the rep named on an older payout still resolves. Ordered oldest first and paged by cursor. |
| GET |
/api/v1/reps/{id} Fetch one rep One rep by their prefixed id. |
| GET |
/api/v1/periods List periods Every commission period this organization has, month, quarter or year. Each carries the timezone its boundaries were decided in, so you can reproduce which side of a boundary a deal fell on. |
| GET |
/api/v1/periods/{id} Fetch one period One period by its prefixed id. |
| GET |
/api/v1/payouts List payouts The current payout for each rep and period, each with its line items: what the rep earned, what was recovered, and what was adjusted. A recalculation replaces a payout rather than editing it, and only the replacement is listed, so summing net_amount over this list gives what is owed once. Amounts are decimal strings and each line names the deal it came from where there is one. |
| GET |
/api/v1/payouts/{id} Fetch one payout One payout by its prefixed id, with its line items. earned_amount is what the period earned, with anything recovered and any correction to an earlier month already counted, and it is the same amount the rep reads on their own statement. It was called gross_amount before, and that name is not reused. An id stays readable after a recalculation replaces it, and superseded_by_id then names the payout that replaced it. On a current payout superseded_by_id is null. |
| GET |
/api/v1/statements/{id} Fetch a statement One payout with the full calculation trace behind it: every step the engine took, in order, with the strategy and version that produced each figure. Takes the payout's id. This is the same trace the rep sees on their own statement. |
| GET |
/api/v1/payroll_files List payroll records Money this organization has recorded as having left, one record per rep per period, with the destination it went to. A void is its own record naming the record it reverses, so summing the column gives what was actually paid. |