Skip to main content
The Escrows API allows you to create and manage secure escrow transactions between buyers and sellers.

Overview

Escrows are secure transactions where funds are held until both parties agree that the transaction is complete. The API provides endpoints to:
  • Create new escrow transactions
  • List and filter your escrows
  • Get detailed information about specific escrows
  • Update, deliver, and cancel pending escrows
  • Get contract details and PDF URLs
  • Receive real-time notifications via webhooks
For critical actions that require user interaction (signing contracts, paying, completing, disputes, and cancellation flows), use Checkout Sessions to redirect users to dhmad.tn.
Your developer account must be associated with a user account to create escrows (unless you provide a sellerEmail). The associated user account must have email verification completed. Phone verification is only required when the buyer accepts and pays, not at escrow creation.

Escrow Modes

When creating an escrow, set the mode field to choose the transaction flow. Both modes share the same statuses (pending → paid → …) but differ in whether a contract is used.

standard

Full flow with a contract both parties sign before payment. Best for services and freelance work between two users.

quick

No contract; buyer pays immediately, then releases funds via complete. Seller deliver is optional. Best for physical or digital products between two users.
Merchant checkout (credits, top-ups, public pay links) is POST /charges, not an escrow mode. mode: "instant" is rejected on create.

Standard mode

  • Set mode: "standard" (default) with contractTerms.
  • A contract is automatically created; both parties must sign before the buyer can pay.
  • Checkout actions: sign_contract → accept_pay → complete. Seller may call Deliver Escrow first. Without completionPolicy that step is optional — the buyer can complete from paid (early release).
  • Provide sellerEmail when the seller is a third party, or omit it to use your associated user as seller.
  • Optional feeBearer ("seller" default, or "buyer") controls who pays platform and developer fees — see Create Escrow.
State flow: pending → paid → (delivered, optional) → completed. Buyer complete is valid from paid or delivered.

Quick mode

  • Set mode: "quick". Do not send contractTerms or autoSign.
  • No contract is created; the response includes contract: null and escrow.mode: "quick".
  • Checkout actions: accept_pay → complete. Seller may call Deliver Escrow first. Without completionPolicy that step is optional. The sign_contract action returns 400 (QUICK_ESCROW_NO_CONTRACT).
  • Use when escrows are between two other parties (sellerEmail required) and you want a faster checkout without a contract — e.g. product sales, digital downloads with buyer confirmation.
  • Minimum internal ledger value (amountTnd) is 5 TND after FX lock (same as standard).
State flow: pending → paid → (delivered, optional) → completed. Buyer complete is valid from paid or delivered.

Quick mode with purchase proof

Add fulfillmentPolicy when you need the seller to prove purchase or shipment before delivery is unlocked — e.g. marketplaces, crowd-shipping, or product-deal apps.
  • Set mode: "quick" and fulfillmentPolicy.type: "purchase_proof_required".
  • After the buyer pays, escrow status stays paid while proofInfo.phase tracks the proof gate (waiting_seller_proof → review → accepted).
  • Checkout actions: accept_pay → submit_proof (seller) → review_proof (buyer) → complete. Seller deliver is optional after proof is accepted; buyer can complete from paid without deliver.
  • Fetch proof files with GET /escrows/:id/proof; handle escrow.proof.* webhooks.
See the Quick Escrow with Proof guide for the full walkthrough.

Delivery confirmation (completion policy)

Add completionPolicy when the seller must deliver before the buyer can release — typical for marketplace digital goods.
  • Set completionPolicy.type: "delivery_confirmation" instead of completionDeadlineDays.
  • buyerReviewDeadlineHours is frozen at creation (default 168, live bounds 24–336).
  • Buyer complete from paid returns DELIVERY_REQUIRED. After deliver they may accept immediately or dispute before completionDeadline.
  • Silence auto-completes. Cannot be combined with completionDeadlineDays or progressiveRelease.
See the Completion Policy guide.

Progressive release (hourly / recurring contracts)

Add progressiveRelease when the total is known up front but the work arrives incrementally — hourly contracts, retainers, or any arrangement billed per period.
  • Include a progressiveRelease object on creation (presence is the opt-in; do not send enabled), optionally with autoApproveHours (the client’s review window). Composes with standard or quick mode. Not available on charges.
  • The escrow stays paid across many payouts. Your backend claims each billing period with Create Payout Request — send face amount + currency or ledger amountTnd. You may do this on the seller’s behalf, so the freelancer takes no weekly action.
  • GET and balance webhooks expose face + TND progressive balances (availableForRelease / reserved / releasedTotal and *Tnd counterparts) plus stable fundedAmount* — do not invent face amounts with tnd / fxRateUsed. On terminal status, float fields are forced to 0.
  • The client approves (approve_release), rejects (reject_release, which opens a dispute for that period only), or does nothing — in which case the period releases automatically at its deadline.
  • Top up the same escrow with add_funds; a zero balance emits escrow.balance.exhausted and leaves the escrow open.
  • End the contract with Close Escrow, which settles owed periods and refunds the unused balance.
State flow: pending → paid → (many partial releases, balance decreasing) → completed on close. See the Progressive Release guide for the full walkthrough.

Auto-release after deliver

Optional completionDeadlineDays on Create Escrow sets how long the buyer has after deliver to release funds, reject delivery, or open a dispute.
  • Integer, platform bounds 3–14 days (default 7 when omitted).
  • Frozen on the escrow at creation and returned on GET as completionDeadlineDays.
  • When the seller calls Deliver, completionDeadline is set to deliveredAt + completionDeadlineDays.
  • If the buyer stays silent, the escrow auto-completes and funds are released. An open dispute pauses the timer.
  • Progressive-release creates reject the field (400). Cannot be combined with completionPolicy (400). Charges never enter delivered and do not use this window.

Mode comparison

estimatedDeliveryDays is a legacy optional field. Omit it for new integrations — it is not used by platform enforcement.

Escrow Statuses

Escrows progress through the following statuses:

pending

Escrow created, waiting for payment. The buyer needs to accept and pay.

paid

Payment received and locked in escrow. The buyer can release funds via a complete checkout session (early release), or the seller can call deliver first (optional). With completionPolicy, deliver is required first. A progressive-release escrow stays here across many partial payouts.

delivered

Service/product delivered. Waiting for buyer to confirm completion, or for the auto-release deadline.

completed

Transaction completed successfully. Funds released to seller.

cancelled

Escrow was cancelled. Funds returned to buyer if payment was made.

Buyer Handling

When creating an escrow, you provide the buyer’s email address. The system handles two scenarios:

Existing User

If the buyer email corresponds to an existing user account:
  • The escrow is linked to their account
  • They receive an in-app notification
  • They receive an email notification
  • They can view and interact with the escrow immediately

New User

If the buyer email doesn’t correspond to an existing user:
  • An invitation email is sent with a registration link
  • The escrow is created with the email stored
  • Once they register using the link, the escrow is automatically linked to their account
  • The registration link includes a secure token for verification

API Endpoints (Direct)

These endpoints can be called directly from your server using your API key:

Checkout Sessions (Redirect)

For actions that require user interaction, use Checkout Sessions to redirect users to dhmad.tn:
  • Sign Contract — User signs the escrow contract (standard mode only)
  • Accept & Pay — Buyer reviews and pays for the escrow (all modes)
  • Submit proof — Seller uploads purchase/shipment proof (Quick Escrow with Proof only)
  • Review proof — Buyer accepts proof or requests corrections (proof escrows only)
  • Complete — Buyer releases funds. Valid when escrow is paid or delivered, except when completionPolicy is set (deliver required first). Not used on charges.
  • Dispute — User opens a dispute
  • Request cancellation — Buyer requests cancellation (paid or delivered; buyer email only)
  • Cancel escrow — Seller cancels immediately (paid or delivered; seller email only)
  • Reject / accept cancellation — Seller responds to a pending buyer cancellation request (seller email)
  • Approve release — Client approves a payout request, releasing that period now (progressive release only; buyer email, metadata.requestId required)
  • Reject release — Client rejects a payout request, opening a dispute for that period only (progressive release only; buyer email, metadata.requestId required)

Escrow amounts support face currencies TND, USD, and EUR via the currency field. The platform ledger uses TND only: amountTnd is locked at creation and used for fees and payouts. See Create Escrow for details.