> ## Documentation Index
> Fetch the complete documentation index at: https://docs.dhmad.tn/llms.txt
> Use this file to discover all available pages before exploring further.

# Create Escrow

> Create an escrow via the public API

<Endpoint method="POST" path="/api/v1/escrows" />

Create a new escrow. Requires API key authentication. The platform fee (DHMAD's percentage) is applied automatically.

Choose the escrow **mode** based on your use case — see [Escrow Modes](/api-reference/escrows/overview#escrow-modes) for a full comparison:

* **`standard`** (default) — contract + sign + pay + deliver + complete. Use with `sellerEmail` for escrows between two parties.
* **`quick`** — no contract; pay → deliver → buyer confirms. Use with `sellerEmail` for product sales without a contract. Optionally add **`fulfillmentPolicy`** for [Quick Escrow with Proof](/guides/quick-escrow-with-proof) (seller uploads proof before delivery).
* **`instant`** — no contract; you are the seller (omit `sellerEmail`); pay → deliver auto-completes. Use for in-app digital goods.

**Developer fee** is only for when the seller is a third party (not your associated account); you can set a developer fee percentage so that a portion of the transaction is credited to your associated user account when the escrow completes.

<RequestExample>
  ```bash cURL theme={null}
  # Standard mode — you are the seller with auto-sign (omit sellerEmail)
  curl -X POST https://dhmad.tn/api/v1/escrows \
    -H "Authorization: Bearer sk_live_your_api_key_here" \
    -H "Content-Type: application/json" \
    -d '{
      "title": "Web Development Service",
      "amount": 1000,
      "currency": "TND",
      "buyerEmail": "buyer@example.com",
      "mode": "standard",
      "estimatedDeliveryDays": 7,
      "contractTerms": "The seller agrees to deliver a fully functional website within 7 days.",
      "autoSign": true
    }'
  ```

  ```bash cURL theme={null}
  # Standard mode — service between two parties (third-party seller)
  curl -X POST https://dhmad.tn/api/v1/escrows \
    -H "Authorization: Bearer sk_live_your_api_key_here" \
    -H "Content-Type: application/json" \
    -d '{
      "title": "Logo design package",
      "amount": 500,
      "currency": "TND",
      "buyerEmail": "buyer@example.com",
      "sellerEmail": "seller@example.com",
      "mode": "standard",
      "estimatedDeliveryDays": 14,
      "contractTerms": "Full design delivery and 2 revisions.",
      "developerFeePercentage": 5
    }'
  ```

  ```bash cURL theme={null}
  # Quick mode with purchase proof — seller must prove purchase before delivery
  curl -X POST https://dhmad.tn/api/v1/escrows \
    -H "Authorization: Bearer sk_live_your_api_key_here" \
    -H "Content-Type: application/json" \
    -d '{
      "title": "iPhone 15 from Dubai",
      "amount": 2500,
      "currency": "TND",
      "buyerEmail": "buyer@example.com",
      "sellerEmail": "seller@example.com",
      "mode": "quick",
      "estimatedDeliveryDays": 7,
      "fulfillmentPolicy": {
        "type": "purchase_proof_required",
        "proofUploadDeadlineHours": 24,
        "buyerReviewDeadlineHours": 24,
        "allowedProofTypes": ["receipt", "tracking_proof", "product_photo"]
      }
    }'
  ```

  ```bash cURL theme={null}
  # Quick mode — product sale, no contract
  curl -X POST https://dhmad.tn/api/v1/escrows \
    -H "Authorization: Bearer sk_live_your_api_key_here" \
    -H "Content-Type: application/json" \
    -d '{
      "title": "Premium template pack",
      "amount": 150,
      "currency": "TND",
      "buyerEmail": "buyer@example.com",
      "sellerEmail": "seller@example.com",
      "mode": "quick",
      "estimatedDeliveryDays": 3
    }'
  ```

  ```bash cURL theme={null}
  # Instant mode — you are the seller (in-app purchase)
  curl -X POST https://dhmad.tn/api/v1/escrows \
    -H "Authorization: Bearer sk_live_your_api_key_here" \
    -H "Content-Type: application/json" \
    -d '{
      "title": "100 AI credits",
      "amount": 25,
      "currency": "TND",
      "buyerEmail": "buyer@example.com",
      "mode": "instant"
    }'
  ```
</RequestExample>

<ResponseExample>
  ```json theme={null}
  {
    "message": "Escrow created successfully",
    "escrow": {
      "id": "507f1f77bcf86cd799439011",
      "title": "Website design",
      "amount": 500,
      "currency": "TND",
      "amountTnd": 500,
      "escrowFee": 25,
      "developerFee": 25,
      "developerFeePercentage": 5,
      "status": "pending",
      "mode": "standard",
      "seller": null,
      "sellerEmail": "seller@example.com",
      "buyer": null,
      "buyerEmail": "buyer@example.com",
      "estimatedDeliveryDays": 14,
      "createdAt": "2024-01-15T10:00:00.000Z"
    },
    "contract": {
      "id": "507f1f77bcf86cd799439012",
      "pdfUrl": null,
      "sellerSigned": false,
      "buyerSigned": false,
      "isFullySigned": false
    }
  }
  ```
</ResponseExample>

For **quick** and **instant** modes, `contract` is `null`.

## Request Body

<ParamField body="title" type="string" required>
  Title of the escrow (1–200 characters).
</ParamField>

<ParamField body="amount" type="number" required>
  Commercial face amount in `currency`. After FX lock, standard and quick modes require internal ledger value (`amountTnd`) of at least **5 TND**; instant mode requires at least **0.01 TND**.
</ParamField>

<ParamField body="currency" type="string" required={false}>
  Face currency: `"TND"` (default), `"USD"`, or `"EUR"`. Ledger, fees, and payouts use `amountTnd` (TND) locked at creation.
</ParamField>

<ParamField body="buyerEmail" type="string" required>
  Email of the buyer. They will be invited to register if they do not have an account.
</ParamField>

<ParamField body="sellerEmail" type="string" required={false}>
  Email of the seller. If omitted, your developer account's associated user account is used as the seller (**required for instant mode**). If provided, the seller is that user or an invite. Use **standard** or **quick** mode for escrows between two other parties.
</ParamField>

<ParamField body="mode" type="string" required={false}>
  `"standard"` (default), `"quick"`, or `"instant"`. See [Escrow Modes](/api-reference/escrows/overview#escrow-modes).

  * **standard** — requires `contractTerms` and `estimatedDeliveryDays`; creates a contract.
  * **quick** — requires `estimatedDeliveryDays`; do not send `contractTerms` or `autoSign`.
  * **instant** — only when you are the seller (omit `sellerEmail`); do not send `contractTerms` or `autoSign`; `estimatedDeliveryDays` optional.
</ParamField>

<ParamField body="estimatedDeliveryDays" type="number" required={false}>
  Required when `mode` is `"standard"` or `"quick"`. Minimum 1 day. Optional for `"instant"` (defaults to 1).
</ParamField>

<ParamField body="contractTerms" type="string" required={false}>
  Required when `mode` is `"standard"`. Contract text (max 10,000 characters). Not allowed for `"quick"` or `"instant"`.
</ParamField>

<ParamField body="autoSign" type="boolean" required={false}>
  Default `false`. If true, the contract is automatically signed by the seller using the signature configured in the developer dashboard. Requires a signature to be set up first. Auto-sign is only available when you are the seller (**omit** `sellerEmail` so your associated user account is used). Do not combine `autoSign: true` with `sellerEmail`. Not applicable for `"quick"` or `"instant"` modes.
</ParamField>

<ParamField body="developerFeePercentage" type="number" required={false}>
  Optional percentage (0–25) of the escrow amount, credited to your developer account's associated user when the escrow completes. **Only allowed when the seller is a third party** (not your associated user account). Not allowed when the seller is your associated account (whether you omit `sellerEmail` or pass that same email); if violated, the API returns **400**. Default is **0**. This amount is deducted from the seller's payout (in addition to the platform fee). If you set a value greater than 0, your developer account **must be associated with a user account** in the developer dashboard; otherwise the request returns **403 Forbidden**.
</ParamField>

<ParamField body="fulfillmentPolicy" type="object" required={false}>
  **Quick Escrow with Proof** — only allowed when `mode` is `"quick"`. Requires the seller to upload purchase/shipment proof after the buyer pays; the buyer reviews on DHMAD before delivery is unlocked. See the [Quick Escrow with Proof guide](/guides/quick-escrow-with-proof).

  * **`type`** (required when set) — must be `"purchase_proof_required"`.
  * **`proofUploadDeadlineHours`** — hours for seller upload after funding (must be within platform bounds, default 6–72h; returns **400** if out of range; default 24h when omitted).
  * **`buyerReviewDeadlineHours`** — hours for buyer review (same bounds; auto-accept if buyer does nothing).
  * **`allowedProofTypes`** — optional UI hints: `receipt`, `order_confirmation`, `product_photo`, `tracking_proof`, `other`. Informational only; DHMAD does not enforce uploads against this list.
</ParamField>

## Quick Escrow with Proof

When `fulfillmentPolicy.type` is `purchase_proof_required`:

1. Buyer pays via `accept_pay` checkout session.
2. Seller uploads proof via `submit_proof` checkout session.
3. Buyer reviews via `review_proof` checkout session (or proof auto-accepts after deadline).
4. Seller delivers only after proof is accepted (`proofInfo.phase` is `accepted` or `accepted_by_timeout`).
5. Fetch proof files with **[GET /escrows/:id/proof](/api-reference/escrows/get-escrow-proof)**; subscribe to `escrow.proof.*` webhooks.

Escrow `status` remains `paid` during the proof gate; use `proofInfo.phase` and proof webhooks for progress.

## Response Fields (escrow object)

<ParamField response="id" type="string">
  Escrow ID.
</ParamField>

<ParamField response="mode" type="string">
  Escrow mode: `standard`, `quick`, or `instant`.
</ParamField>

<ParamField response="escrowFee" type="number">
  Platform fee in TND (deducted from seller).
</ParamField>

<ParamField response="developerFee" type="number">
  Developer commission amount in TND (calculated from `developerFeePercentage`). Credited to the developer's associated user account when funds are released.
</ParamField>

<ParamField response="developerFeePercentage" type="number">
  The percentage set at creation (0–25).
</ParamField>

## Checkout page and fees

When you redirect users to a [Checkout Session](/api-reference/checkout-sessions/create-session), the DHMAD checkout page shows the **platform service fee** (paid by seller) and, if you set `developerFeePercentage` when creating the escrow, the **application / app fee** (with your app name when configured). Sellers see the total deductions before completing the flow.

## Errors

### 400 Bad Request – Instant mode with third-party seller

When `mode` is `"instant"` and `sellerEmail` is provided:

```json theme={null}
{
  "error": "Bad Request",
  "message": "Instant mode is only available when you are the seller (omit sellerEmail). For escrows between two other parties, use mode: standard (with a contract) or mode: quick (no contract)."
}
```

Use **standard** or **quick** mode and provide `sellerEmail` for escrows between two other parties.

### 400 Bad Request – Contract terms on quick/instant mode

When `mode` is `"quick"` or `"instant"` and `contractTerms` is provided:

```json theme={null}
{
  "error": "Bad Request",
  "message": "Contract terms are not applicable for quick mode (no contract is created). Use mode: standard to include a contract."
}
```

### 400 Bad Request – Developer fee when seller is your associated account

When `developerFeePercentage` is greater than 0 and the seller (resolved from the request) is your developer account's associated user:

```json theme={null}
{
  "error": "Bad Request",
  "message": "Developer fee is not allowed when the seller is your associated user account. Use developerFeePercentage only when the seller is a third party (different from your associated account)."
}
```

Omit `developerFeePercentage` or set it to 0 when you are the seller (or when the seller email is your associated account).

### 400 Bad Request – Auto-sign not allowed

When `autoSign` is `true` but the seller is not your associated user account (for example, you provided `sellerEmail` for a third party, or the seller has not registered yet):

```json theme={null}
{
  "error": "Bad Request",
  "message": "Auto-sign is only available when you are the seller (omit sellerEmail). When specifying a sellerEmail, the seller must sign the contract themselves."
}
```

Other auto-sign failures return **400** with messages such as:

* No signature configured in the developer dashboard.
* Developer account not associated with a user account (when `sellerEmail` was provided for a third party).
* `sellerEmail` refers to a user who has not registered yet (seller must sign after registering).

When you are the seller, omit `sellerEmail`, set up your signature in the [Developer Dashboard](https://developer.dhmad.tn/dashboard), and ensure your developer account is associated with your DHMAD user account.

### 403 Forbidden – Developer fee without associated user

If you send `developerFeePercentage` greater than 0 and your developer account has no associated user account:

```json theme={null}
{
  "error": "Forbidden",
  "message": "Developer account must be associated with a user account to collect developer fees. Please associate your account in the developer dashboard."
}
```

Associate your developer account with a user account in the [Developer Dashboard](https://developer.dhmad.tn/dashboard) to collect developer fees.

### 403 Forbidden – No seller and no associated user

If you omit `sellerEmail` and your developer account has no associated user:

```json theme={null}
{
  "error": "Forbidden",
  "message": "Developer account must be associated with a user account to create escrows. Please associate your account in the developer dashboard."
}
```
