/dapi/v1 routes share one format for money, ids, casing, idempotency and pagination, and one set of limits. Send amounts as decimal strings, and send an Idempotency-Key with POST /dapi/v1/payouts and other writes that book a payment.
Money
An amount is a decimal string in the major unit of the asset:"500.00", "0.9247", "1204.500000". Do not send a fractional JSON number, an atomic-unit integer or exponent notation. Rates use the same format. feeBps is an integer number of basis points.
Precision depends on the route:
A payin, swap or payout takes
amount, the side sent, or amountTo, the side received, and not both. HEVN prices the other side.
In JavaScript and Go a decimal arrives as a string, so a typeof x === "number" check skips it. Parse with a decimal type.
Ids
An id is a prefixed, opaque string. Store it as text. Do not parse it, derive it or assume a length.
An id of the wrong kind in a body or query field returns
400 invalid_id, with the expected prefix in details. In a path it returns the 404 of that resource.
Casing
A contact’s
address, and the fields and holder of a bank or payer requisite, ignore unknown keys. A misspelt streetAddress counts as missing: on a bank contact that needs an address, POST /dapi/v1/contacts returns 422 validation_failed, and the message names the missing keys in snake_case.
The fields keys on PUT /dapi/v1/documents/{documentId}/content are document field names such as registration_number and address.street_address. A refusal that requires one of these fields returns its name. See Fill a document’s fields by hand.
Idempotency-Key
Every write acceptsIdempotency-Key, and no route requires it. The value matches ^[A-Za-z0-9._:-]{1,128}$.
Derive the key from an id in your system.
To book two identical payouts within 2 hours, send a different key with each.
Why a retry cannot pay twice
Each payout has one slot in the paying wallet, the main wallet or a sub account: an ERC-4337 nonce derived from the payout. The network accepts one operation per slot. When the slot is used or an operation is in flight, the call returns409 already_funded, 409 payment_slot_consumed or 409 funding_in_progress. After payment_slot_consumed an operation has landed, possibly reverted, and signing again has no effect. Retrying a confirm lists the next step for each.
Escrow actions and payments sent from the HEVN app use the same slots.
Pagination
A list returns a cursor page.cursor, the unchanged nextCursor of the previous page, until the response omits nextCursor.
A cursor sent to a different query returns 400 invalid_cursor. Lists have no offset and no total count. GET /dapi/v1/transactions/summary takes the GET /dapi/v1/transactions filters and returns totals.
Status codes
No route returns
204. Location and pollUrl are paths from the host root, including /dapi/v1.
The API sends no webhooks. After a 202, read pollUrl with backoff until status is final. See HTTP client for the helper and Rate limits for read limits.
A client’s pollUrl is /dapi/v1/client. Poll it with the new cl_… in X-Hevn-Account.
A payout with authorization: "wallet" has no confirm call. Poll GET /dapi/v1/payouts/{payoutId} after the customer’s wallet sends the transfer.
Errors
A refusal returns{ "error": { "code", "message", "details" } }. Branch on code. The fields, the details keys and the full list of codes are in Errors.
Rate limits
A request over a rate limit returns429 rate_limited with a Retry-After header. Wait that many seconds, then retry.
Requests with different
X-Hevn-Account values share the write and read counters of one credential.
POST /dapi/v1/auth/refresh has no login limit. It counts as a write.
Booking and confirming a signed payout counts as two writes. Poll with backoff (Status codes), and read GET /dapi/v1/transactions once for the account where you can, not once per client.
A sandbox host may run with the credential and account limits off. Test the Retry-After path before you go live. Sandbox amount caps and faucet rules are listed in Sandbox.
Lifetimes
Other lifetimes are on the REST API pages: the refresh token on Exchange a signed login challenge, the sign-in window session on Create a sign-in window session, the payin quote on Create an incoming transfer quote, the escrow windows on Open an escrow and the escrow chain read on Reconcile one escrow. After a sign-in window session expires, create a new one. The replay windows of an
Idempotency-Key are in Idempotency-Key.