Overview
How to authenticate against the Hashira API, and the conventions every endpoint shares.
The Hashira API is a JSON HTTP API served under /v1. Everything the dashboard does is
available through it: catalog and pricing, customers, subscriptions and invoices, Pix charges with
split payments, sub-account withdrawals, transactional email, and OTLP telemetry ingestion.
The Reference section in the sidebar is generated from the same Zod schemas the endpoints validate requests with, so request shapes cannot drift away from what the server actually accepts. Each endpoint page carries a playground you can send real requests from.
Authenticating
Every request carries a project API key as a bearer token:
curl https://api.hashira.stellarcode.space/v1/products \
-H "Authorization: Bearer $HASHIRA_API_KEY"A missing key answers 401 MISSING_API_KEY; an unrecognised one answers 401 INVALID_API_KEY.
Live mode and test mode
An API key is bound to one project and carries a mode. Test-mode and live-mode records are stored separately, and charges created with a test key are routed to the payment gateway's sandbox instead of production.
Nothing in the request says which mode you are in — the key alone decides. The same GET /products
returns a different catalog depending on which key you present.
The playground on each reference page sends real requests to this host. Use a test-mode key: a live key will create real charges and move real money.
Errors
Failures answer with a flat envelope whose error is a stable English identifier, never display
copy. Map it to your own wording; the identifiers are part of the contract and the wording is not.
{ "error": "INVOICE_NOT_OPEN" }Validation failures add a fields object keyed by field name:
{
"error": "VALIDATION_ERROR",
"fields": { "amountCents": ["Too small: expected number to be >0"] }
}Two details worth knowing about fields. It is flattened, so a failure nested inside an array —
items[0].priceId, say — reports under items. And a rule that spans several fields reports under
whichever single field the rule names: the "at least one of taxId, email or phone" rule on
customers reports under taxId.
Status codes follow the usual split: 400 for a malformed or invalid request, 404 for something
that does not exist, 409 when the request is well-formed but the resource is in the wrong state,
and 502 when the payment gateway itself failed — which means the request was fine and can be
retried.
Pagination
Collections answer with a cursor envelope:
{ "data": [], "nextCursor": "0199a1b2-c3d4-7000-8000-000000000000" }Ids are UUIDv7, so they sort by creation time and an id doubles as a stable keyset cursor. Pass the
previous response's nextCursor as cursor to fetch the next page; null means you have reached
the end. Results are ordered newest first.
Other conventions
Creations answer 200, not 201. Every timestamp is an ISO-8601 string in UTC. Every monetary
amount is an integer number of cents in the currency named alongside it — there are no floats.