Escrow
Create, advance, and settle escrow transactions between buyers and sellers. Supports milestone-based payouts, negotiated splits, disputes, and admin resolution. All endpoints require x-api-key and x-company-id.
Query
/v1/escrowList escrows for the company with optional filters. Supports pagination.
| Field | Type | Required | Description |
|---|---|---|---|
| status | string (query) | No | Filter by escrow status (PENDING, ACTIVE, COMPLETED, CANCELLED, DISPUTED). |
| buyerId | uuid (query) | No | Filter to escrows where this user is the buyer. |
| sellerId | uuid (query) | No | Filter to escrows where this user is the seller. |
| startDate | ISO date (query) | No | Start of the date range. |
| endDate | ISO date (query) | No | End of the date range. |
| limit | integer (query) | No | Max number of results to return. |
| offset | integer (query) | No | Number of results to skip (for paging). |
curl -X GET "https://api.switchlock.co.zw/v1/escrow" \
-H "x-api-key: zl_sk_your_key_here" \
-H "x-company-id: cmp_01HXYZ..."{
"data": [
{
"id": "esc_01hx...",
"status": "ACTIVE",
"totalAmount": "10000",
"currency": "USD",
"buyer": { "id": "...", "name": "Tendai M." },
"seller": { "id": "...", "name": "Farai N." },
"createdAt": "2026-06-23T10:00:00.000Z"
}
],
"total": 42
}/v1/escrow/activeShortcut to list all currently ACTIVE escrows for the company.
curl -X GET "https://api.switchlock.co.zw/v1/escrow/active" \
-H "x-api-key: zl_sk_your_key_here" \
-H "x-company-id: cmp_01HXYZ..."[{ "id": "esc_01hx...", "status": "ACTIVE", ... }]/v1/escrow/:idRetrieve full details for a single escrow, including items, milestones, and split plan.
| Field | Type | Required | Description |
|---|---|---|---|
| id | uuid (path) | Yes | UUID of the escrow. |
curl -X GET "https://api.switchlock.co.zw/v1/escrow/value" \
-H "x-api-key: zl_sk_your_key_here" \
-H "x-company-id: cmp_01HXYZ..."{
"id": "esc_01hx...",
"status": "ACTIVE",
"externalReference": "INV-001",
"totalAmount": "10000",
"currency": "USD",
"splitPlan": {
"system_fee_cents": "200",
"service_fee_cents": "300",
"seller_payout_cents": "9500"
},
"milestones": [],
"items": [{ "name": "Laptop", "quantity": 1, "pricePerUnit": 10000 }]
}/v1/escrow/:id/timelineRetrieve the ordered event timeline for an escrow — every state change, note, and actor recorded.
| Field | Type | Required | Description |
|---|---|---|---|
| id | uuid (path) | Yes | UUID of the escrow. |
curl -X GET "https://api.switchlock.co.zw/v1/escrow/value/timeline" \
-H "x-api-key: zl_sk_your_key_here" \
-H "x-company-id: cmp_01HXYZ..."[
{ "event": "INITIATED", "actor": "COMPANY", "at": "2026-06-23T10:00:00.000Z" },
{ "event": "DELIVERY_NOTED", "actor": "SELLER", "at": "2026-06-24T09:00:00.000Z" },
{ "event": "GOODS_RECEIVED", "actor": "BUYER", "at": "2026-06-25T14:00:00.000Z" },
{ "event": "FUNDS_RELEASED", "actor": "SYSTEM", "at": "2026-06-25T14:01:00.000Z" }
]Initiate
buyerAccountId must belong to the buyer and have sufficient balance. Funds are held (not transferred) until release.
/v1/escrow/initiateStart a new escrow. Locks funds from the buyer's account and creates escrow records with optional milestones.
| Field | Type | Required | Description |
|---|---|---|---|
| buyerId | uuid | Yes | UUID of the buyer user. |
| sellerId | uuid | Yes | UUID of the seller user. |
| buyerAccountId | uuid | Yes | Account to hold funds from. |
| sellerAccountId | uuid | No | Seller account to receive payout; uses default if omitted. |
| items | array | Yes | Line items: name, description?, quantity, pricePerUnit. |
| externalReference | string | Yes | Your unique order reference. |
| externalInvoiceNumber | string | No | Invoice number for display. |
| splitPlan | object | No | Custom split: system_fee_cents, service_fee_cents, seller_payout_cents. |
| feePayer | enum | No | Who pays the fee: BUYER or SELLER. |
| milestones | array | No | Milestone definitions: title, description?, percentage (0–100). Percentages must sum to 100. |
curl -X POST "https://api.switchlock.co.zw/v1/escrow/initiate" \
-H "x-api-key: zl_sk_your_key_here" \
-H "x-company-id: cmp_01HXYZ..." \
-H "Content-Type: application/json" \
-d '{
"buyerId": "string",
"sellerId": "string",
"buyerAccountId": "string",
"sellerAccountId": "string",
"items": [],
"externalReference": "string",
"externalInvoiceNumber": "string",
"splitPlan": {},
"feePayer": "string",
"milestones": []
}'{
"id": "esc_01hx...",
"status": "ACTIVE",
"totalAmount": "10000",
"currency": "USD",
"createdAt": "2026-06-23T10:00:00.000Z"
}Delivery & Goods Received
/v1/escrow/:id/delivery-noteSeller records that goods or services have been dispatched. Advances the escrow to DELIVERY_NOTED state.
| Field | Type | Required | Description |
|---|---|---|---|
| id | uuid (path) | Yes | UUID of the escrow. |
| items | array | Yes | Items delivered: itemId, quantity, price_per_item. |
| notes | string | No | Optional delivery notes or tracking information. |
curl -X POST "https://api.switchlock.co.zw/v1/escrow/value/delivery-note" \
-H "x-api-key: zl_sk_your_key_here" \
-H "x-company-id: cmp_01HXYZ..." \
-H "Content-Type: application/json" \
-d '{
"id": "string",
"items": [],
"notes": "string"
}'{ "status": "DELIVERY_NOTED", "updatedAt": "2026-06-24T09:00:00.000Z" }/v1/escrow/:id/goods-receivedBuyer confirms receipt of goods or services. Advances the escrow to GOODS_RECEIVED.
| Field | Type | Required | Description |
|---|---|---|---|
| id | uuid (path) | Yes | UUID of the escrow. |
| items | array | Yes | Items received: itemId, quantity, price_per_item. |
| notes | string | No | Optional receipt notes. |
curl -X POST "https://api.switchlock.co.zw/v1/escrow/value/goods-received" \
-H "x-api-key: zl_sk_your_key_here" \
-H "x-company-id: cmp_01HXYZ..." \
-H "Content-Type: application/json" \
-d '{
"id": "string",
"items": [],
"notes": "string"
}'{ "status": "GOODS_RECEIVED", "updatedAt": "2026-06-25T14:00:00.000Z" }Release
Releasing an escrow is idempotent — send an x-idempotency-key header to safely retry without double-paying.
/v1/escrow/:id/releaseFinalize the escrow and transfer funds to the seller per the split plan. For milestone escrows, pass a milestoneId query parameter to release a single milestone.
| Field | Type | Required | Description |
|---|---|---|---|
| id | uuid (path) | Yes | UUID of the escrow. |
| milestoneId | uuid (query) | No | Release a specific milestone instead of the full amount. |
curl -X POST "https://api.switchlock.co.zw/v1/escrow/value/release" \
-H "x-api-key: zl_sk_your_key_here" \
-H "x-company-id: cmp_01HXYZ..." \
-H "Content-Type: application/json" \
-d '{
"id": "string",
"milestoneId": "string"
}'{
"status": "COMPLETED",
"sellerPayout": "9500",
"systemFee": "200",
"serviceFee": "300",
"transactionId": "txn_..."
}Negotiations
Either party can propose a revised split plan. The other party must explicitly accept or reject it.
/v1/escrow/:id/negotiatePropose a new split plan for an escrow.
| Field | Type | Required | Description |
|---|---|---|---|
| id | uuid (path) | Yes | UUID of the escrow. |
| newSplitPlan | object | Yes | Proposed split: system_fee_cents, service_fee_cents, seller_payout_cents. |
| actor | enum | Yes | Who is proposing: BUYER or SELLER. |
| notes | string | No | Reason for the adjustment. |
curl -X POST "https://api.switchlock.co.zw/v1/escrow/value/negotiate" \
-H "x-api-key: zl_sk_your_key_here" \
-H "x-company-id: cmp_01HXYZ..." \
-H "Content-Type: application/json" \
-d '{
"id": "string",
"newSplitPlan": {},
"actor": "string",
"notes": "string"
}'{ "negotiationId": "neg_01hx...", "status": "PENDING" }/v1/escrow/:id/negotiate/:negId/acceptAccept a pending negotiation proposal.
| Field | Type | Required | Description |
|---|---|---|---|
| id | uuid (path) | Yes | UUID of the escrow. |
| negId | uuid (path) | Yes | UUID of the negotiation. |
| actor | enum (body) | Yes | BUYER or SELLER — must be the counterparty who did not propose. |
curl -X POST "https://api.switchlock.co.zw/v1/escrow/value/negotiate/value/accept" \
-H "x-api-key: zl_sk_your_key_here" \
-H "x-company-id: cmp_01HXYZ..." \
-H "Content-Type: application/json" \
-d '{
"id": "string",
"negId": "string",
"actor": "string"
}'{ "negotiationId": "neg_01hx...", "status": "ACCEPTED" }/v1/escrow/:id/negotiate/:negId/rejectReject a pending negotiation proposal.
| Field | Type | Required | Description |
|---|---|---|---|
| id | uuid (path) | Yes | UUID of the escrow. |
| negId | uuid (path) | Yes | UUID of the negotiation. |
| actor | enum (body) | Yes | BUYER or SELLER. |
curl -X POST "https://api.switchlock.co.zw/v1/escrow/value/negotiate/value/reject" \
-H "x-api-key: zl_sk_your_key_here" \
-H "x-company-id: cmp_01HXYZ..." \
-H "Content-Type: application/json" \
-d '{
"id": "string",
"negId": "string",
"actor": "string"
}'{ "negotiationId": "neg_01hx...", "status": "REJECTED" }Milestone Adjustments
For milestone-based escrows, either party can propose a revised payout for a specific milestone before it is released.
/v1/escrow/:id/milestones/:milestoneId/adjustPropose a revised payout amount for a milestone.
| Field | Type | Required | Description |
|---|---|---|---|
| id | uuid (path) | Yes | UUID of the escrow. |
| milestoneId | uuid (path) | Yes | UUID of the milestone. |
| actor | enum (body) | Yes | BUYER or SELLER. |
| proposedSellerPayoutCents | integer | Yes | New proposed payout in cents. |
| reason | string | No | Justification for the adjustment. |
curl -X POST "https://api.switchlock.co.zw/v1/escrow/value/milestones/value/adjust" \
-H "x-api-key: zl_sk_your_key_here" \
-H "x-company-id: cmp_01HXYZ..." \
-H "Content-Type: application/json" \
-d '{
"id": "string",
"milestoneId": "string",
"actor": "string",
"proposedSellerPayoutCents": 1000,
"reason": "string"
}'{ "negotiationId": "neg_01hx...", "status": "PENDING" }/v1/escrow/:id/milestones/:milestoneId/negotiate/:negId/acceptAccept a milestone adjustment proposal.
| Field | Type | Required | Description |
|---|---|---|---|
| id | uuid (path) | Yes | Escrow UUID. |
| milestoneId | uuid (path) | Yes | Milestone UUID. |
| negId | uuid (path) | Yes | Negotiation UUID. |
| actor | enum (body) | Yes | BUYER or SELLER. |
curl -X POST "https://api.switchlock.co.zw/v1/escrow/value/milestones/value/negotiate/value/accept" \
-H "x-api-key: zl_sk_your_key_here" \
-H "x-company-id: cmp_01HXYZ..." \
-H "Content-Type: application/json" \
-d '{
"id": "string",
"milestoneId": "string",
"negId": "string",
"actor": "string"
}'{ "negotiationId": "neg_01hx...", "status": "ACCEPTED" }/v1/escrow/:id/milestones/:milestoneId/negotiate/:negId/rejectReject a milestone adjustment proposal.
| Field | Type | Required | Description |
|---|---|---|---|
| id | uuid (path) | Yes | Escrow UUID. |
| milestoneId | uuid (path) | Yes | Milestone UUID. |
| negId | uuid (path) | Yes | Negotiation UUID. |
| actor | enum (body) | Yes | BUYER or SELLER. |
curl -X POST "https://api.switchlock.co.zw/v1/escrow/value/milestones/value/negotiate/value/reject" \
-H "x-api-key: zl_sk_your_key_here" \
-H "x-company-id: cmp_01HXYZ..." \
-H "Content-Type: application/json" \
-d '{
"id": "string",
"milestoneId": "string",
"negId": "string",
"actor": "string"
}'{ "negotiationId": "neg_01hx...", "status": "REJECTED" }Disputes & Cancellation
/v1/escrow/:id/disputeRaise a formal dispute. The escrow is frozen and escalated for admin review.
| Field | Type | Required | Description |
|---|---|---|---|
| id | uuid (path) | Yes | UUID of the escrow. |
| actor | enum (body) | Yes | BUYER or SELLER — the party raising the dispute. |
| reason | string | Yes | Reason for the dispute. |
curl -X POST "https://api.switchlock.co.zw/v1/escrow/value/dispute" \
-H "x-api-key: zl_sk_your_key_here" \
-H "x-company-id: cmp_01HXYZ..." \
-H "Content-Type: application/json" \
-d '{
"id": "string",
"actor": "string",
"reason": "string"
}'{ "status": "DISPUTED", "disputeId": "dsp_01hx..." }/v1/escrow/:id/cancelCancel an escrow and return funds to the buyer. Only available before funds are released.
| Field | Type | Required | Description |
|---|---|---|---|
| id | uuid (path) | Yes | UUID of the escrow. |
| actor | enum | Yes | BUYER, SELLER, or ADMIN. |
| reason | string | Yes | Reason for cancellation. |
curl -X POST "https://api.switchlock.co.zw/v1/escrow/value/cancel" \
-H "x-api-key: zl_sk_your_key_here" \
-H "x-company-id: cmp_01HXYZ..." \
-H "Content-Type: application/json" \
-d '{
"id": "string",
"actor": "string",
"reason": "string"
}'{ "status": "CANCELLED", "refundTransactionId": "txn_..." }/v1/escrow/:id/admin-resolveAdmin-only: resolve a disputed escrow by imposing a final split plan.
| Field | Type | Required | Description |
|---|---|---|---|
| id | uuid (path) | Yes | UUID of the disputed escrow. |
| newSplitPlan | object | Yes | Final split: system_fee_cents, service_fee_cents, seller_payout_cents. |
| adminId | string | Yes | ID of the admin resolving the dispute. |
curl -X POST "https://api.switchlock.co.zw/v1/escrow/value/admin-resolve" \
-H "x-api-key: zl_sk_your_key_here" \
-H "x-company-id: cmp_01HXYZ..." \
-H "Content-Type: application/json" \
-d '{
"id": "string",
"newSplitPlan": {},
"adminId": "string"
}'{ "status": "RESOLVED", "finalSplit": { ... } }