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

# Embedded escrow

> Build a branded goods-and-services flow with TRON USDT holding, release, refund and dispute review.

Run the customer experience in your application while Rach provides dedicated escrow
wallets and settlement mechanics. Your backend calls the CaaS API; protect its key and
keep it out of browsers and mobile apps. The partner API is separate from the Rach P2P
trading interface. There is no required trading-interface redirect, hosted widget or
escrow SDK in this delivery.

Agree [pilot and operating terms](/guides/escrow-pilot) and confirm environment enablement
with Rach before collecting funds. A published specification or simulated response does
not establish mainnet settlement evidence or country eligibility.

## Custody and supported scope

| Item             | Behavior                                                                                                                                      |
| ---------------- | --------------------------------------------------------------------------------------------------------------------------------------------- |
| Asset            | USDT on TRON (TRC-20). EVM and Solana transfers are separate; they do not provide escrow adapters.                                            |
| Holding          | A dedicated Rach-controlled wallet per deal. This is custodial wallet escrow, not a TRON escrow smart contract.                               |
| Participants     | Distinct E.164 phone numbers; each must already have a tenant-linked Rach TRON wallet.                                                        |
| Release          | The full agreed principal goes to the seller's linked Rach wallet.                                                                            |
| Refund           | The full agreed principal returns to the buyer's linked Rach wallet, which can differ from the funding address.                               |
| Authorization    | The tenant API key authorizes ordinary release/refund. `on_behalf_of` records an assertion, not an independently verified customer signature. |
| Dispute          | Authorized Rach staff decide full release or refund; the settlement worker executes it.                                                       |
| Deposit recovery | Rach staff can separately return confirmed partial, excess or late deposits to the named buyer after verifying entitlement.                   |

The partner receives no escrow private keys. Legal custody, compliance duties and the
partner's authorization role must be stated in the agreement; the API does not decide
regulatory status.

## API operations

All partner calls use `X-API-Key`. The public CaaS service base is
`https://api.rach.finance/caas`; append the `/v1/...` paths below. Confirm escrow
enablement for your tenant before funding a deal.
See the [CaaS reference](/api-reference/caas-introduction).

| Method | Path                                        | Purpose                                                             |
| ------ | ------------------------------------------- | ------------------------------------------------------------------- |
| `POST` | `/v1/escrows`                               | Create a deal (`201`).                                              |
| `GET`  | `/v1/escrows`                               | Tenant-scoped list; `state`, `limit` (1–200), `offset`.             |
| `GET`  | `/v1/escrows/{id}`                          | Read state and payout evidence.                                     |
| `GET`  | `/v1/escrows/{id}/events`                   | Read creation, transitions and action history.                      |
| `POST` | `/v1/escrows/{id}/release`                  | Authorize seller payment.                                           |
| `POST` | `/v1/escrows/{id}/refund`                   | Authorize buyer refund.                                             |
| `POST` | `/v1/escrows/{id}/dispute`                  | Record a reason for review.                                         |
| `POST` | `/v1/escrows/{id}/cancel`                   | Close a still-unfunded deal when the deposit observer reports zero. |
| `GET`  | `/v1/escrows/{id}/recoveries`               | Read separately tracked deposit recoveries.                         |
| `POST` | `/v1/escrows/{id}/events/{event_id}/replay` | Requeue a persisted webhook event (`202`).                          |

Rach's dispute-decision and deposit-recovery authorization routes require staff permissions
and are excluded from the public partner specification.

## Provision and open

Provision each participant with `POST /v1/tron/users/provision`, using `phone_number`.
For an existing wallet owned by another tenant, complete the consent/linking flow first.
Escrow creation checks membership, participant freeze status and wallet existence. It does
not automatically provision customers or perform KYC by validating their phone numbers.

```json theme={null}
{
  "reference": "chainzap-deal-8821",
  "rail": "TRON",
  "token": "USDT",
  "amount": "25.00",
  "buyer_phone": "+2348012345678",
  "seller_phone": "+2348087654321",
  "auto_release_hours": 72
}
```

Omit `chain_id`. The create `reference` is unique within your tenant and is the idempotency
key. Retry identical terms to receive the original deal and address; changed terms return
`409`. New deal admission requires enabled deposit scanning and sponsored payouts, plus a
successful sponsor-readiness check; otherwise it returns `503`.

`auto_release_hours` is optional (0–8760). Zero uses the configured default, currently no
automatic release. The agreed duration is persisted and starts when confirmed funding is
recorded. A dispute prevents automatic release. Explain the inspection window in your
customer terms before enabling it.

An illustrative live response is:

```json theme={null}
{
  "id": "esc_example",
  "reference": "chainzap-deal-8821",
  "state": "CREATED",
  "rail": "TRON",
  "network": "mainnet",
  "token": "USDT",
  "amount": "25000000",
  "escrow_address": "<dedicated TRON address returned by Rach>",
  "funding_expires_at": "2026-09-21T12:00:00Z",
  "payout_pending": false,
  "created_at": "2026-09-20T12:00:00Z",
  "updated_at": "2026-09-20T12:00:00Z"
}
```

**Amount units differ:** create requests use whole-USDT decimal strings; live responses,
webhook data and recovery amounts use integer base-unit strings. `"25000000"` means 25
USDT (six decimals). Use integer/decimal arithmetic, not floating point.

## Funding and settlement

The buyer sends the exact principal in USDT over TRON to the dedicated address. External
wallet/exchange authorization remains part of the funding flow. Rach records `FUNDED`
from confirmed USDT deposits; a partner cannot assert it by supplying a transaction hash.

| State                   | Meaning                                                                                      |
| ----------------------- | -------------------------------------------------------------------------------------------- |
| `CREATED`               | Full principal has not yet been established. Partial or not-yet-observed deposits may exist. |
| `FUNDED`                | At least the agreed principal is confirmed. Check `payout_pending`.                          |
| `DISPUTED`              | Rach review is required; no auto-release.                                                    |
| `RELEASED`              | Principal payout to the seller was confirmed.                                                |
| `REFUNDED`              | Principal payout to the buyer was confirmed.                                                 |
| `CANCELLED` / `EXPIRED` | Deal is closed; these states do not themselves return deposits.                              |

The default funding window is 24 hours. A positive partial deposit or observer failure
prevents automatic expiry. Late deposits can still arrive at a closed address and must
use the recovery process; closing a database deal cannot disable its blockchain address.

For release, send this optional body to `/v1/escrows/{id}/release`:

```json theme={null}
{"on_behalf_of":"BUYER","reason":"buyer confirmed delivery"}
```

Refund uses `/refund`; a dispute uses `/dispute` and requires a nonempty `reason`.
Your API key is the authorizing party regardless of `on_behalf_of`. Collect customer
consent according to the agreed operating terms.

Payout calls return `202` while state remains `FUNDED` (or `DISPUTED` for an admin decision)
and `payout_pending` is true. Report payment complete only after terminal state and
`payout_tx_hash`. Pending repeats conflict; read persisted state after `409` or an uncertain
response. Actions do not accept a separate idempotency key.

A dispute and payout claim serialize on the same row: if the dispute wins, only Rach can
resolve; if payout was already claimed, a new dispute is refused. A broadcast transaction
cannot be recalled. The payout's direction is stored explicitly, independently of reason
text. Tenant and participant freezes are checked before payout and again by the TRON worker.

## Partial, excess and late deposits

Rach staff can authorize a separately identified recovery after verifying ownership and
entitlement, including for third-party deposits. Recoveries reserve confirmed unallocated
funds, serialize concurrent requests and leave the principal outcome unchanged. An open
partial deposit can be recovered after the funding deadline; the deal then closes.
Principal owed under a funded/disputed deal cannot be consumed as an excess recovery.

Read `/recoveries` for the recovery reference, base-unit amount, recipient, reason,
`PENDING`/`SETTLED`/`FAILED` status and transaction hash. Pending recovery is not payment
confirmation. A failed attempt requires an explicit new authorization; unknown outcomes
remain reserved. The recipient is the named buyer's linked wallet, not an arbitrary address.

## Webhooks and reconciliation

Register your receiver in the CaaS dashboard. Escrow events are persisted with their state
change and delivered asynchronously. Verify `X-Rach-Signature: sha256=<hex>` as HMAC-SHA256
over the exact raw body using your webhook secret.

```json theme={null}
{
  "event_id": "esc_evt_123",
  "event": "escrow.funded",
  "created_at": "2026-09-20T12:03:00Z",
  "data": {
    "id": "esc_example",
    "reference": "chainzap-deal-8821",
    "state": "FUNDED",
    "rail": "TRON",
    "network": "mainnet",
    "token": "USDT",
    "amount": "25000000",
    "escrow_address": "<dedicated address>",
    "payout_pending": false,
    "created_at": "2026-09-20T12:00:00Z",
    "updated_at": "2026-09-20T12:03:00Z"
  }
}
```

Events include `escrow.created`, `escrow.funded`, `escrow.payout_pending`,
`escrow.released`, `escrow.refunded`, `escrow.disputed`, `escrow.cancelled`,
`escrow.expired`, `escrow.payout_failed`, `escrow.recovery_pending`,
`escrow.recovery_settled` and `escrow.recovery_failed`.

Delivery is **at least once**. Deduplicate by `event_id`; retries/replays preserve it.
Failures are retried with capped backoff and survive process restart. Delivery order is
not guaranteed, so fetch current state before updating a time-sensitive customer screen.
Read `/events` for stable IDs and actor/reason metadata, and use the replay endpoint for
redelivery. Read `/recoveries` for recovery-specific details. The events describe persisted
snapshots; a delayed event need not be the current state.

## Sandbox limitations

Test keys (`rach_sk_test_…`) or account test mode simulate supported mutations without
creating custody wallets or persistent deals. **Never fund a simulated address.** Reads
pass through to normal handlers, not a separate sandbox datastore, so a simulated ID
cannot be polled as a stored deal.

Simulated release/refund return terminal states immediately. They do not reproduce live
pending/confirmation behavior or emit settlement webhooks. Simulation does not provide
full live validation and currently echoes the request amount in whole tokens rather than
live base units. Use fixtures for UI states and complete the agreed settlement acceptance
exercise before live use.

## Disputes and operating terms

The API records reasons, identities and history, including creation and asserted
`on_behalf_of` metadata. A resolved payout exposes the recorded admin reasoning as
`resolution_note`. Evidence submission, appeals, adjudication rules, staffing and SLAs
are part of the agreed operating process; this release does not provide evidence-file
upload or appeal endpoints.

Confirm [entity, compliance, countries, pricing and pilot terms](/guides/escrow-pilot).
Network sponsorship describes on-chain payment of costs, not a free-service commitment.
