XKOVA Docs

Escrow and Claims

Escrow lets a sender commit value before the recipient is ready to receive it. The sender signs an escrow that holds the funds, the recipient gets a claim link, and the recipient proves they are the intended party with a one-time code before choosing how to receive. Use escrow when the recipient is not yet onboarded, not yet known by wallet address, or when you want the recipient to choose the destination.

When to use escrow instead of a direct send

A direct send needs a recipient wallet to push value to. Escrow does not. The sender commits the funds and the recipient resolves where they go later, from a link. Reach for escrow when:

  • The recipient has no wallet yet, or has not onboarded.
  • You know the recipient by email or phone, not by address.
  • You want the recipient to choose the destination at claim time.

If the recipient is a known, onboarded member with a wallet, a direct send is simpler.

The flow end to end

An escrow is created and signed by the sender, the same non-custodial way a payment is. That produces a claim link delivered to the recipient. The recipient verifies a one-time code, then resolves the claim by choosing a path. Resolution drives settlement, which releases the held value.

flowchart TD
  A[Sender creates escrow] --> B[Sender signs intent]
  B --> C[Funds held in escrow]
  C --> D[Claim link sent to recipient]
  D --> E[Recipient verifies one-time code]
  E --> F[Recipient resolves a path]
  F --> G[Settlement releases funds]

Creating an escrow

The sender's application creates the escrow and the sender signs it in their own wallet. Escrow uses a single signature over the create intent. The signing session returns the typed data to sign and a short lived token the member's wallet uses to connect. Once submitted, the API relays the signed intent and the escrow holds the funds. The non-custodial mechanics are the same as a payment, covered in the Non-custodial Model.

The recipient claim

The recipient lands on the claim flow from the claim link. The link carries a token that authenticates the recipient side without an API key, so this is a browser surface the recipient drives, not a backend call. The claim runs in these steps.

  1. Fetch context. The recipient opens the link and sees the claim context, what is being claimed and from whom.
  2. Send code. A one-time code is issued to the recipient's chosen channel, email or phone.
  3. Verify code. The recipient enters the code. Verifying proves the recipient controls that channel before any value moves.
  4. Resolve. The recipient chooses a path. They can resolve to an external wallet, or wait, which leaves the escrow open until it expires.
A claim token can be refreshed into a fresh token for the same underlying escrow, which is how an expired or stale link is reissued without creating a new escrow.
Every resolution path requires a verified one-time code first, including choosing to wait. If the code session has expired by the time the recipient resolves, they are asked to request a new code and verify again before the claim can complete.

Release and expiry

Resolving to a destination drives the corresponding settlement flow, which releases the held value to the recipient. Choosing to wait leaves the escrow open until its expiry. The release itself settles on chain like any other transfer, so the same confirmation rules apply, see Transfers and Settlement.

Only the sender can cancel an escrow, and only before it expires. Once the expiry passes, the held value returns to the sender, not the recipient, and recovering it no longer needs the sender's signature. Treat expiry as the sender getting their funds back, not as the recipient's claim eventually completing on its own.

Reading state

List your tenant's escrows newest first with cursor pagination, fetch a single escrow for its current state, or read its event timeline to see each transition. Direct sends and escrows also appear together in a unified transactions view when you want both in one feed.

Errors worth handling per step

The error catalog documents every code; these are the ones each step most commonly returns.

StepCodes
Createvalidation_failed, token_not_enabled, chain_not_allowed, compliance_blocked, authorization_denied
Sign and submitunauthorized (an expired or invalid signing token), invalid_state, authorization_invalid (the platform could not confirm the signed authorization for this movement: it is missing, expired, already consumed, or no longer binds the signed intent), compliance_case_open
Claim journeynot_found (an unknown or superseded claim token), invalid_state (already resolved or expired), unauthorized (the one-time code is not verified yet), validation_failed
Cancelinvalid_state (already claimed, cancelled, or past expiry), not_found, validation_failed

Related

For the exact request and response shapes of the escrow and claim operations, see the operations list or try them live in the interactive reference.