voided or reclaimed deal can still be refunded, if something was captured before the hold was released.
Every transition you drive is one POST /dapi/v1/escrow/{escrowId}/actions that you sign with your developer key, on your own wallet. You are the operator of every deal you create; escrow never takes X-Hevn-Account, because the caller is always you. Like /clients* and /connect/sessions, it refuses the header with 400 account_scope_conflict and details.reason = "selfScopedRoute". See Sessions.
The states money is in
A deal carries two amounts, and they are what you branch on:capturableAmount— money out of the buyer’s wallet, held in the contract, not yet paid to the seller.capturemoves it to the seller,voidreturns it to the buyer, and the buyer’s ownreclaimreturns it after the hold window.refundableAmount— money already paid to the seller that you can still send back. A refund leaves your own wallet, not the seller’s, so keep a working balance in the deal’s token.
status is a label for the last thing that happened, not a decision input. Read availableActions — the server computes it from the amounts, the windows and what already landed on chain — and pick from it. A draft nobody approved in time has an empty availableActions; there is no expired status and nothing sweeps a stale deal.
Amounts are decimal strings in the token’s major unit, rendered at the token’s precision: "100.000000" for USDC. token is a symbol — USDC or EURC — never an address. The full status vocabulary is in Escrow actions.
The three parties
All three must be different accounts, and both parties must be clients linked to you. HEVN binds sender and receiver through the relationship Sign in with HEVN writes; an account you merely referred never qualifies, and a stranger’s account id answers
422 receiver_not_a_client or 404 client_not_found. The addresses are each party’s Base smart wallet at creation time, and the deal is immutable: its terms are hashed into an on-chain payment record.
The three windows
You give three durations and HEVN resolves them once, at creation, each measured from the end of the one before it.
A duration is
^\d{1,4}[smhd]$ — 30m, 1h, 14d. You never compute a timestamp, which is what makes a retry safe: repeating POST /dapi/v1/escrow with the same Idempotency-Key returns the same deal with the same absolute windows, no matter how much later it arrives. Different durations under the same key answer 409 idempotency_key_reused with details.escrowId.
void is the exception with no clock on it: while anything is capturable, you can always hand it back.
What it costs
feeBps on the deal is your ceiling, an integer in basis points. capture and charge may take any fee up to it; the fee goes to your own Base smart wallet, which HEVN derives — there is no feeReceiver to send. fee = amount × feeBps / 10000, the receiver gets the rest, and a refund returns the gross amount from your wallet without clawing the fee back.
Set the ceiling at creation. It is part of the immutable deal, so a deal created with feeBps: 0 can never take a commission.
HEVN sponsors the gas for every action and charges nothing on top.
Before you start
- Both parties are clients linked to you and are
ready— see Clients. - Your account may operate escrow. HEVN enables that, in the sandbox as in production; nothing in the API grants it. Without it every escrow call is refused — see Going live.
- The buyer’s wallet holds the token when you authorize, not when you create. Creating a deal moves nothing.
- Call escrow with your own access token and no
X-Hevn-Account— the header answers400 account_scope_conflicton every escrow route. - Your developer key still exists and the call leaves an allowlisted source IP. Both are re-checked on every request, and again immediately before HEVN co-signs an action — see Developer key.
Idempotency-Key from an id your own system already owns, pass it in from the caller, and
keep it identical across every retry of the same payment.
A marketplace order, end to end
Every example below uses the client from HTTP client and thesign_payload helper from Signing.
Order A-1187: Northwind Trading Ltd (cl_7YQ2Kf3mN8) buys 100 USDC of parts from Ardenne Fabrication SARL (cl_2ABxR9dL4m), and you take 2.5% when it ships.
1
Open the deal, and let the buyer approve it
One call creates the deal and prepares the buyer’s approval — the on-chain permission that lets you pull the money later. The response echoes the create’s key as Nothing has moved.
action.idempotencyKey. The approval is the buyer’s to sign with their own key, not yours.Response — 201, Location: /dapi/v1/escrow/esc_5Qb4e17c9d
availableActions becomes ["authorize", "charge"] once the buyer’s approval lands on chain; read the deal until it does.2
Lock the buyer's funds in the contract
authorize pulls the amount out of the buyer’s wallet into the escrow contract. It happens once per deal: authorize less than maxAmount and the remainder is unusable, so authorize the order total.Response — 200
3
Ship it, and capture with your commission
capture pays the seller and takes your fee in the same action. It is repeatable up to capturableAmount, so a partial shipment is a partial capture.captured with refundableAmount: "100.000000" — the gross is what you can still send back.When the order does not go to plan
void and refund keep working when your relationship with a client is paused or your profile is suspended, and so does the buyer’s reclaim, so held money is never stranded.
Next: Escrow actions
Every action, the window it is legal in, the amount it takes, and the state it leaves behind.