Skip to content

Response format

Every SaleSprint endpoint follows the same response contract, so a client can parse any endpoint the same way. The machine-readable source of truth is the generated API Reference; this page explains the shared shapes behind it.

Returned as its bare object — no wrapper.

// GET /admin/companies/{id}
{
"id": "0f8c…",
"name": "Acme Ltd",
"code": "ACME",
"status": "active"
}

Every list endpoint returns the same envelope: an items array plus a pagination object. items is always an array — never null — even when empty.

// GET /admin/companies?page=1&page_size=20
{
"items": [ { "id": "…", "name": "Acme Ltd" } ],
"pagination": {
"page": 1,
"page_size": 20,
"total": 137,
"total_pages": 7,
"has_next": true,
"has_prev": false
}
}
Field Meaning
page 1-based page number that produced these items
page_size maximum items per page (the effective, clamped size)
total total items across all pages
total_pages number of pages at this page_size
has_next a page after this one exists
has_prev a page before this one exists

Request pagination with the page and page_size query parameters. page defaults to 1, page_size to 20, and page_size is clamped to a maximum of 200. The pagination object always echoes the effective values, so what you read back is what the query actually ran with. Some small reference lists always return every row as a single complete page.

Endpoints with nothing to return (logout, delete, “reset link sent”) return a short message.

{ "message": "logged out" }

Every non-2xx response is RFC 9457 problem detail, served as application/problem+json, extended with a stable code and — for validation failures — a per-field errors array.

// HTTP 422
{
"type": "about:blank",
"title": "Unprocessable Entity",
"status": 422,
"code": "validation_failed",
"detail": "one or more fields are invalid",
"errors": [
{ "field": "email", "code": "invalid", "message": "must be a valid email" }
]
}

Switch on code, not on detail. code is stable and machine-readable; detail and title are human prose and may change. errors is present on validation failures, one entry per offending field, where field is the dotted path (email, items.0.qty).

HTTP code When
400 bad_request Malformed request
401 unauthorized Missing or invalid authentication
403 forbidden Authenticated but not permitted
404 not_found Resource does not exist
409 conflict Collides with current state (e.g. duplicate)
422 validation_failed Parsed but one or more fields are invalid
429 rate_limited Throttled
500 internal_error Unexpected server-side failure

The same shape is returned for framework-level errors (request validation, unknown routes, panics) as for errors a handler raises deliberately, so there is only ever one error shape to handle.