Reference
API reference
Authentication, endpoints, objects, errors and limits.
Base URL: https://smartcontractsescrow.net/api/v1 · Version header on every response:
Escrow-Version: 2026-09-01 · Machine-readable spec: openapi.yaml
Authentication
Server-to-server only. Send your secret key as a bearer token:
Authorization: Bearer sce_3f9a1c2b4d5e6f70_Qm9…
- Keys belong to a seller account and act as that seller.
- Only a SHA-256 hash is stored — a lost key cannot be recovered; revoke it and create a new one.
- Never ship a key to a browser or mobile app. Cookie sessions from the web app do not work on these endpoints, and API keys do not work on the web-app endpoints.
- Keys are managed in Seller dashboard → Integrations (max 10 active).
Errors
Every non-2xx response has the same envelope:
{
"error": {
"type": "invalid_request_error",
"code": "validation_failed",
"message": "Request validation failed.",
"details": { "amount": ["Ensure this value is greater than or equal to 0.01."] }
}
}
| HTTP | type | Typical code |
|---|---|---|
| 400 | invalid_request_error | validation_failed, missing_submission_details |
| 401 | authentication_error | unauthenticated (missing, invalid or revoked key) |
| 403 | permission_error | forbidden |
| 404 | invalid_request_error | not_found (also returned for other merchants' objects) |
| 409 | invalid_request_error | idempotency_conflict, session_completed, escrow_not_funded, invalid_state |
| 429 | rate_limit_error | rate_limited — honour Retry-After |
Idempotency
Send Idempotency-Key: <unique string ≤255 chars> on POST /checkout/sessions.
- Same key + same body → the original response is replayed (
Idempotent-Replayed: true). - Same key + different body →
409 idempotency_conflict. - Validation failures (4xx before creation) are not stored, so you can fix and retry.
- Use one key per attempt (e.g. a UUID stored with your order), and reuse it only when retrying a request whose outcome you don't know (timeout, connection reset).
Pagination
List endpoints use cursors: ?limit=25 (max 100), then follow next / previous URLs.
{ "object": "list", "data": [ … ], "next": "https://…?cursor=cD0yMDI2…", "previous": null }
Rate limits
120 requests/minute per key by default. Exceeding it returns 429
with Retry-After.
Endpoints
GET /account
Verify credentials. Returns seller_code, trading_name, verification_status, masked key.
POST /checkout/sessions
| Field | Type | Notes |
|---|---|---|
title | string ≤255 | Required. Shown to the buyer and used as the escrow title |
amount | decimal string | Required. ≥ 0.01. The order total the buyer owes you (fees are added on top) |
currency | string | USD only (default) |
description | string | Optional |
line_items[] | {name, quantity, unit_amount, sku?} | Display only (≤100). Not required to sum to amount (discounts, tax) |
milestones[] | {title, amount, description?} | Optional staged release (≤20). Must sum to amount. Default: one milestone for the full amount |
external_reference | string ≤255 | Your order ID. Echoed on every event |
customer_email | Prefill only; any signed-in buyer can complete the session | |
metadata | object | ≤50 keys (≤40 chars) with string values (≤500 chars). Echoed on escrow objects |
success_url / cancel_url | URL | Where the hosted page sends the buyer back |
platform | string | woocommerce, shopify, custom, … (analytics) |
expires_in | int seconds | 900 – 604800. Default 86400 (24 h) |
Response 201 — a Checkout Session.
GET /checkout/sessions · GET /checkout/sessions/{id}
Filter the list with ?external_reference=1001.
POST /checkout/sessions/{id}/expire
Invalidate an unused link (e.g. the customer changed their cart). Completed sessions → 409.
GET /escrows · GET /escrows/{id}
Escrows created through your checkout sessions. Filters: status, external_reference.
{id} is the escrow's uuid; its TR-… reference code is accepted too.
Identifiers. Object ids are uuids; store them as strings. Each escrow also has a
human-readable reference_code (TR-<yyyymmdd>.<6 digits>.<deal amount in cents>, e.g.
TR-20261125.482913.14999) to show customers and support staff, plus a dispute_reference
(DS-########) once disputed. Reference codes are not secrets and never grant access.
POST /escrows/{id}/milestones/{milestone_id}/submit
Tell the buyer the order has shipped / the work is delivered.
{ "submission_details": "DHL 1234567890 — delivered to reception" }
- The escrow must be funded (
IN_ESCROWorWORK_IN_PROGRESS) → otherwise409 escrow_not_funded. - The milestone must be
PENDINGorREVISION_REQUESTED→ otherwise409 invalid_state. - Returns the updated Escrow. The buyer then approves (funds released to your wallet), requests a revision, or disputes.
GET /events
Every event ever emitted for your account, newest first; filter with ?type=escrow.funded.
Use it to reconcile after downtime instead of relying solely on webhook delivery.
Objects
Checkout Session object
{
"id": "cs_5b1e0c9a7d3f4e2a1b6c8d0e",
"object": "checkout.session",
"status": "OPEN",
"url": "https://smartcontractsescrow.net/checkout/Zt4…",
"title": "Order #1001",
"description": "",
"currency": "USD",
"amount": "149.99",
"line_items": [{ "name": "Canon EOS R50", "quantity": 1, "unit_amount": "149.99" }],
"milestones": [],
"external_reference": "1001",
"customer_email": "buyer@example.com",
"metadata": {},
"success_url": "https://shop.example.com/thank-you/1001",
"cancel_url": "https://shop.example.com/cart",
"platform": "custom",
"escrow": null,
"expires_at": 1790000000,
"completed_at": null,
"created": 1789913600
}
status: OPEN → COMPLETED (buyer confirmed; escrow is set) or EXPIRED. url is
null unless OPEN. Timestamps are Unix seconds.
Escrow object
{
"id": "4f8c2d1e-7b3a-4e9f-a2c6-1d5e8f0b3a7c",
"object": "escrow",
"reference_code": "TR-20260920.482913.14999",
"dispute_reference": null,
"title": "Order #1001",
"status": "IN_ESCROW",
"currency": "USD",
"amount": "149.99",
"fees": "3.00",
"total": "152.99",
"funded_amount": "152.99",
"buyer": { "email": "buyer@example.com" },
"checkout_session": "cs_5b1e0c9a7d3f4e2a1b6c8d0e",
"external_reference": "1001",
"metadata": {},
"milestones": [
{ "id": "9a1b3c5d-2e4f-4a6b-8c0d-e1f2a3b4c5d6", "object": "milestone",
"reference_code": "MS-40918273", "title": "Deliver: Order #1001", "amount": "149.99",
"status": "PENDING", "description": "", "submission_details": "" }
],
"created": 1789913700
}
Escrow status values: PENDING_FUNDING, AWAITING_PAYMENT, WAITING_PAYMENT_CONFIRMATION,
PARTIALLY_FUNDED, IN_ESCROW, WORK_IN_PROGRESS, COMPLETED, DISPUTED, CANCELLED,
DECLINED, CLOSED, DEADLINE_EXPIRED.
amount is what you receive when all milestones are approved; fees are paid by the buyer.