Skip to main content
All /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 accepts Idempotency-Key, and no route requires it. The value matches ^[A-Za-z0-9._:-]{1,128}$. Derive the key from an id in your system.
Do not generate the key in the helper that sends the request, from a clock or at random. Do not change it on a retry. A new key books a second payment.
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 returns 409 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.
Send 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.
Funding refusals report details.available and details.required in atomic units: "3000000" is 3 USDC. Do not mix them with major-unit amounts.

Rate limits

A request over a rate limit returns 429 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.

Setting limits

Field sizes on API requests are on the REST API page of each operation. These limits apply to settings in the HEVN app:

Next: Accounts