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

# Programmable Escrow and On-Chain Dispute Resolution

> Lock USDC in a smart contract on Arc testnet with milestone-based release conditions and arbiter-mediated on-chain dispute resolution.

FlareHQ's escrow service lets you lock USDC in a smart contract on Arc testnet until both parties confirm that conditions are met. If either side disagrees, either party can raise a dispute — at which point the designated arbiter reviews the evidence and resolves the outcome on-chain. No funds move unless the contract says so.

## Use Cases

<CardGroup cols={2}>
  <Card title="Freelance Milestone Payments" icon="code">
    Lock the project fee in escrow before work begins. The client releases funds when they accept the deliverable.
  </Card>

  <Card title="Marketplace Transactions" icon="shop">
    Hold buyer funds until the seller ships and the buyer confirms receipt, eliminating chargeback risk.
  </Card>

  <Card title="AI Agent Job Completion" icon="robot">
    Pay autonomous agents only when their on-chain wallet reports a task as complete, verified by an arbiter contract.
  </Card>

  <Card title="Grant Milestones" icon="trophy">
    Release tranche payments only when milestone conditions written into the `condition` field are satisfied.
  </Card>
</CardGroup>

## How Escrow Works

1. **Create** — The depositor locks USDC in the escrow contract, naming a beneficiary and an arbiter.
2. **Both confirm** — When both depositor and beneficiary call `confirmDelivery`, the contract releases funds to the beneficiary automatically.
3. **Dispute** — If either party raises a dispute, funds are frozen and the arbiter reviews the case.
4. **Resolve** — The arbiter resolves the dispute on-chain to send funds to either party.

## Creating an Escrow

<Steps>
  ### Install and Initialise the SDK

  ```bash theme={null}
  npm install @flarehq/sdk
  ```

  ```typescript theme={null}
  import { FlareHQ } from '@flarehq/sdk';

  const flarehq = new FlareHQ({ apiKey: process.env.FLAREHQ_SECRET_KEY! });
  ```

  ### Create the Escrow

  Pass the amount, the beneficiary (provider) address, the arbiter, and a Unix timestamp deadline.

  <CodeGroup>
    ```typescript SDK theme={null}
    const escrow = await flarehq.escrow.create({
      amount: '200.00',
      provider: '0xWorkerAddress',
      arbiter: '0x3500000000000000000000000000000000008004',
      releaseDeadline: 1770000000, // Unix timestamp
    });

    console.log('Escrow reference:', escrow.reference);
    console.log('Explorer:', escrow.explorerUrl);
    ```

    ```bash REST theme={null}
    curl -X POST https://flarehq.xyz/api/escrow/create \
      -H "Authorization: Bearer fhq_sec_..." \
      -H "Content-Type: application/json" \
      -d '{
        "depositorSCA": "0xYourWalletAddress",
        "depositorWalletId": "your-wallet-uuid",
        "beneficiarySCA": "0xWorkerAddress",
        "amount": "200.00",
        "deadlineHours": 72,
        "condition": "Deliver completed API integration with passing test suite",
        "webhookUrl": "https://example.com/webhooks/flarehq"
      }'
    ```
  </CodeGroup>

  <Note>
    The REST API accepts `deadlineHours` (hours from now) rather than an absolute Unix timestamp. The SDK's `releaseDeadline` field accepts a Unix epoch integer and is converted server-side.
  </Note>

  ### Verify the Escrow is Active

  The response includes a transaction hash you can inspect on Arc's block explorer.

  ```json theme={null}
  {
    "success": true,
    "escrow": {
      "reference": "escrow_m8k2p1_ab12cd",
      "amount": 200.0,
      "currency": "USDC",
      "depositorSCA": "0xYourWalletAddress",
      "beneficiarySCA": "0xWorkerAddress",
      "status": "ACTIVE",
      "condition": "Deliver completed API integration with passing test suite",
      "deadline": "2025-01-18T10:00:00.000Z"
    },
    "txHash": "0xabc123...",
    "explorerUrl": "https://testnet.arcscan.app/tx/0xabc123...",
    "contractAddress": "0x...",
    "message": "200.00 USDC locked in escrow on Arc Testnet. Both parties must confirm to release."
  }
  ```
</Steps>

## REST API Parameters

<ParamField body="depositorSCA" type="string" required>
  The wallet address of the party locking the funds. This wallet must hold sufficient USDC.
</ParamField>

<ParamField body="depositorWalletId" type="string" required>
  The wallet ID used to authorise the on-chain transactions. Retrieve this from `GET /api/agent/status`.
</ParamField>

<ParamField body="beneficiarySCA" type="string" required>
  The wallet address of the party that receives funds on release.
</ParamField>

<ParamField body="amount" type="string" required>
  USDC amount to lock, as a decimal string, e.g. `"200.00"`.
</ParamField>

<ParamField body="deadlineHours" type="number">
  Hours from now until the auto-release deadline. Defaults to `24`. See the warning below.
</ParamField>

<ParamField body="condition" type="string">
  Human-readable release condition stored on-chain and shown to both parties, e.g. `"Deliver completed API integration"`.
</ParamField>

<ParamField body="webhookUrl" type="string">
  URL to receive escrow lifecycle events. See [Webhook Events](#webhook-events) below.
</ParamField>

## Releasing Funds

Either the depositor or the beneficiary calls the release endpoint to confirm delivery. The contract tracks confirmations — funds are released to the beneficiary only when **both** parties have confirmed.

```bash theme={null}
curl -X POST https://flarehq.xyz/api/escrow/release \
  -H "Authorization: Bearer fhq_sec_..." \
  -H "Content-Type: application/json" \
  -d '{
    "reference": "escrow_m8k2p1_ab12cd",
    "callerSCA": "0xYourWalletAddress"
  }'
```

<ResponseField name="released" type="boolean">
  `true` when both parties have confirmed and funds have transferred to the beneficiary.
</ResponseField>

<ResponseField name="message" type="string">
  Human-readable status. If only one party has confirmed, the message says so and instructs you to wait for the other party.
</ResponseField>

## Raising a Dispute

Either party can raise a dispute at any time while the escrow is `ACTIVE`. This freezes the funds and notifies the arbiter.

```bash theme={null}
curl -X POST https://flarehq.xyz/api/escrow/dispute \
  -H "Authorization: Bearer fhq_sec_..." \
  -H "Content-Type: application/json" \
  -d '{
    "reference": "escrow_m8k2p1_ab12cd",
    "callerSCA": "0xWorkerAddress",
    "reason": "Client is unresponsive and has not reviewed the delivered work within the agreed 48-hour window."
  }'
```

Once a dispute is raised, the escrow status changes to `DISPUTED` and neither party can release funds unilaterally. The arbiter reviews the case and resolves the outcome on-chain.

## Checking Escrow Status

```bash theme={null}
curl "https://flarehq.xyz/api/escrow/status?reference=escrow_m8k2p1_ab12cd" \
  -H "Authorization: Bearer fhq_sec_..."
```

## Escrow Lifecycle

```
ACTIVE ──── both parties confirm ──→ RELEASED
  │
  ├──── either party disputes ────→ DISPUTED ──── arbiter resolves ──→ RELEASED / REFUNDED
  │
  └──── deadline passes (no dispute raised) ─────────────────────────→ RELEASED (auto)
```

| Status     | Description                                             |
| ---------- | ------------------------------------------------------- |
| `ACTIVE`   | Funds are locked; awaiting confirmations                |
| `RELEASED` | Funds transferred to beneficiary                        |
| `DISPUTED` | A dispute is open; arbiter is reviewing                 |
| `REFUNDED` | Arbiter ruled in the depositor's favour; funds returned |

## The Arbiter

The default arbiter address is `0x3500000000000000000000000000000000008004`, the agent registry contract on Arc testnet. You can substitute any address — a multisig, a DAO, or a trusted third-party contract — by passing a different `arbiter` value when creating the escrow via the SDK.

## Webhook Events

| Event              | Fired when                                                 |
| ------------------ | ---------------------------------------------------------- |
| `escrow.created`   | Escrow is confirmed on-chain and is `ACTIVE`               |
| `escrow.released`  | Both parties confirmed and USDC transferred to beneficiary |
| `dispute.created`  | A dispute is raised; escrow moves to `DISPUTED`            |
| `dispute.resolved` | Arbiter resolves the dispute on-chain                      |

### Example Payload — `escrow.created`

```json theme={null}
{
  "event": "escrow.created",
  "reference": "escrow_m8k2p1_ab12cd",
  "depositorSCA": "0xYourWalletAddress",
  "beneficiarySCA": "0xWorkerAddress",
  "amount": 200.0,
  "currency": "USDC",
  "condition": "Deliver completed API integration with passing test suite",
  "deadline": "2025-01-18T10:00:00.000Z",
  "txHash": "0xabc123...",
  "explorerUrl": "https://testnet.arcscan.app/tx/0xabc123...",
  "createdAt": "2025-01-15T10:00:00.000Z"
}
```

You can verify any escrow transaction on the Arc block explorer:

```
https://testnet.arcscan.app/tx/{txHash}
```

<Warning>
  **Automatic release at deadline.** If `deadlineHours` passes and no dispute has been raised, the escrow contract releases funds automatically to the beneficiary. Raise a dispute **before** the deadline if you believe conditions have not been met — you cannot dispute an escrow once it has auto-released.
</Warning>
