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:

code
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:

json
{
  "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."] }
  }
}
HTTPtypeTypical code
400invalid_request_errorvalidation_failed, missing_submission_details
401authentication_errorunauthenticated (missing, invalid or revoked key)
403permission_errorforbidden
404invalid_request_errornot_found (also returned for other merchants' objects)
409invalid_request_erroridempotency_conflict, session_completed, escrow_not_funded, invalid_state
429rate_limit_errorrate_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.

json
{ "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

FieldTypeNotes
titlestring ≤255Required. Shown to the buyer and used as the escrow title
amountdecimal stringRequired. ≥ 0.01. The order total the buyer owes you (fees are added on top)
currencystringUSD only (default)
descriptionstringOptional
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_referencestring ≤255Your order ID. Echoed on every event
customer_emailemailPrefill only; any signed-in buyer can complete the session
metadataobject≤50 keys (≤40 chars) with string values (≤500 chars). Echoed on escrow objects
success_url / cancel_urlURLWhere the hosted page sends the buyer back
platformstringwoocommerce, shopify, custom, … (analytics)
expires_inint seconds900 – 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.

json
{ "submission_details": "DHL 1234567890 — delivered to reception" }
  • The escrow must be funded (IN_ESCROW or WORK_IN_PROGRESS) → otherwise 409 escrow_not_funded.
  • The milestone must be PENDING or REVISION_REQUESTED → otherwise 409 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

json
{
  "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

json
{
  "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.