SwitchLock Docs
API Reference/Escrow

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.

Escrow lifecycle
1
Initiate
2
Delivery Note
3
Goods Received
4
Release

Query

GET
/v1/escrow

List escrows for the company with optional filters. Supports pagination.

Auth
FieldTypeRequiredDescription
statusstring (query)NoFilter by escrow status (PENDING, ACTIVE, COMPLETED, CANCELLED, DISPUTED).
buyerIduuid (query)NoFilter to escrows where this user is the buyer.
sellerIduuid (query)NoFilter to escrows where this user is the seller.
startDateISO date (query)NoStart of the date range.
endDateISO date (query)NoEnd of the date range.
limitinteger (query)NoMax number of results to return.
offsetinteger (query)NoNumber 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..."
Response Example
{
  "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
}
GET
/v1/escrow/active

Shortcut to list all currently ACTIVE escrows for the company.

Auth
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..."
Response Example
[{ "id": "esc_01hx...", "status": "ACTIVE", ... }]
GET
/v1/escrow/:id

Retrieve full details for a single escrow, including items, milestones, and split plan.

Auth
FieldTypeRequiredDescription
iduuid (path)YesUUID 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..."
Response Example
{
  "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 }]
}
GET
/v1/escrow/:id/timeline

Retrieve the ordered event timeline for an escrow — every state change, note, and actor recorded.

Auth
FieldTypeRequiredDescription
iduuid (path)YesUUID 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..."
Response Example
[
  { "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.

POST
/v1/escrow/initiate

Start a new escrow. Locks funds from the buyer's account and creates escrow records with optional milestones.

Auth
FieldTypeRequiredDescription
buyerIduuidYesUUID of the buyer user.
sellerIduuidYesUUID of the seller user.
buyerAccountIduuidYesAccount to hold funds from.
sellerAccountIduuidNoSeller account to receive payout; uses default if omitted.
itemsarrayYesLine items: name, description?, quantity, pricePerUnit.
externalReferencestringYesYour unique order reference.
externalInvoiceNumberstringNoInvoice number for display.
splitPlanobjectNoCustom split: system_fee_cents, service_fee_cents, seller_payout_cents.
feePayerenumNoWho pays the fee: BUYER or SELLER.
milestonesarrayNoMilestone 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": []
}'
Response Example
{
  "id": "esc_01hx...",
  "status": "ACTIVE",
  "totalAmount": "10000",
  "currency": "USD",
  "createdAt": "2026-06-23T10:00:00.000Z"
}

Delivery & Goods Received

POST
/v1/escrow/:id/delivery-note

Seller records that goods or services have been dispatched. Advances the escrow to DELIVERY_NOTED state.

Auth
FieldTypeRequiredDescription
iduuid (path)YesUUID of the escrow.
itemsarrayYesItems delivered: itemId, quantity, price_per_item.
notesstringNoOptional 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"
}'
Response Example
{ "status": "DELIVERY_NOTED", "updatedAt": "2026-06-24T09:00:00.000Z" }
POST
/v1/escrow/:id/goods-received

Buyer confirms receipt of goods or services. Advances the escrow to GOODS_RECEIVED.

Auth
FieldTypeRequiredDescription
iduuid (path)YesUUID of the escrow.
itemsarrayYesItems received: itemId, quantity, price_per_item.
notesstringNoOptional 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"
}'
Response Example
{ "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.

POST
/v1/escrow/:id/release

Finalize 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.

Auth
FieldTypeRequiredDescription
iduuid (path)YesUUID of the escrow.
milestoneIduuid (query)NoRelease 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"
}'
Response Example
{
  "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.

POST
/v1/escrow/:id/negotiate

Propose a new split plan for an escrow.

Auth
FieldTypeRequiredDescription
iduuid (path)YesUUID of the escrow.
newSplitPlanobjectYesProposed split: system_fee_cents, service_fee_cents, seller_payout_cents.
actorenumYesWho is proposing: BUYER or SELLER.
notesstringNoReason 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"
}'
Response Example
{ "negotiationId": "neg_01hx...", "status": "PENDING" }
POST
/v1/escrow/:id/negotiate/:negId/accept

Accept a pending negotiation proposal.

Auth
FieldTypeRequiredDescription
iduuid (path)YesUUID of the escrow.
negIduuid (path)YesUUID of the negotiation.
actorenum (body)YesBUYER 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"
}'
Response Example
{ "negotiationId": "neg_01hx...", "status": "ACCEPTED" }
POST
/v1/escrow/:id/negotiate/:negId/reject

Reject a pending negotiation proposal.

Auth
FieldTypeRequiredDescription
iduuid (path)YesUUID of the escrow.
negIduuid (path)YesUUID of the negotiation.
actorenum (body)YesBUYER 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"
}'
Response Example
{ "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.

POST
/v1/escrow/:id/milestones/:milestoneId/adjust

Propose a revised payout amount for a milestone.

Auth
FieldTypeRequiredDescription
iduuid (path)YesUUID of the escrow.
milestoneIduuid (path)YesUUID of the milestone.
actorenum (body)YesBUYER or SELLER.
proposedSellerPayoutCentsintegerYesNew proposed payout in cents.
reasonstringNoJustification 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"
}'
Response Example
{ "negotiationId": "neg_01hx...", "status": "PENDING" }
POST
/v1/escrow/:id/milestones/:milestoneId/negotiate/:negId/accept

Accept a milestone adjustment proposal.

Auth
FieldTypeRequiredDescription
iduuid (path)YesEscrow UUID.
milestoneIduuid (path)YesMilestone UUID.
negIduuid (path)YesNegotiation UUID.
actorenum (body)YesBUYER 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"
}'
Response Example
{ "negotiationId": "neg_01hx...", "status": "ACCEPTED" }
POST
/v1/escrow/:id/milestones/:milestoneId/negotiate/:negId/reject

Reject a milestone adjustment proposal.

Auth
FieldTypeRequiredDescription
iduuid (path)YesEscrow UUID.
milestoneIduuid (path)YesMilestone UUID.
negIduuid (path)YesNegotiation UUID.
actorenum (body)YesBUYER 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"
}'
Response Example
{ "negotiationId": "neg_01hx...", "status": "REJECTED" }

Disputes & Cancellation

POST
/v1/escrow/:id/dispute

Raise a formal dispute. The escrow is frozen and escalated for admin review.

Auth
FieldTypeRequiredDescription
iduuid (path)YesUUID of the escrow.
actorenum (body)YesBUYER or SELLER — the party raising the dispute.
reasonstringYesReason 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"
}'
Response Example
{ "status": "DISPUTED", "disputeId": "dsp_01hx..." }
POST
/v1/escrow/:id/cancel

Cancel an escrow and return funds to the buyer. Only available before funds are released.

Auth
FieldTypeRequiredDescription
iduuid (path)YesUUID of the escrow.
actorenumYesBUYER, SELLER, or ADMIN.
reasonstringYesReason 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"
}'
Response Example
{ "status": "CANCELLED", "refundTransactionId": "txn_..." }
POST
/v1/escrow/:id/admin-resolve

Admin-only: resolve a disputed escrow by imposing a final split plan.

Auth
FieldTypeRequiredDescription
iduuid (path)YesUUID of the disputed escrow.
newSplitPlanobjectYesFinal split: system_fee_cents, service_fee_cents, seller_payout_cents.
adminIdstringYesID 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"
}'
Response Example
{ "status": "RESOLVED", "finalSplit": { ... } }

Next steps