ClearPact API

Programmable escrow for autonomous agent payments. Lock funds, verify conditions, settle automatically.

Quick Start

Get from zero to your first escrow in 3 steps. No signup form, no OAuth. Just an email and an API call.

1

Get an API Key

Create a key with your email. You'll get a key that starts with cpk_live_. Save it — it's only shown once.

curl
curl -X POST https://clearpact.polsia.app/api/keys \
  -H "Content-Type: application/json" \
  -d '{"email": "dev@example.com", "name": "My First Key"}'
2

Create an Escrow

Lock USDC between two parties with conditions for release.

curl
curl -X POST https://clearpact.polsia.app/api/escrow \
  -H "Content-Type: application/json" \
  -H "X-API-Key: cpk_live_YOUR_KEY_HERE" \
  -d '{
    "payer": "0xAliceWallet",
    "payee": "0xBobWallet",
    "amount": "250.00",
    "token": "USDC",
    "conditions": [
      {"type": "task_completion", "description": "Complete data analysis"}
    ]
  }'
3

Settle When Conditions Are Met

Verify conditions and release funds to the payee.

curl
curl -X POST https://clearpact.polsia.app/api/escrow/ESCROW_ID/settle \
  -H "Content-Type: application/json" \
  -H "X-API-Key: cpk_live_YOUR_KEY_HERE" \
  -d '{
    "verifications": {"0": {"completed": true}},
    "actor": "0xAliceWallet"
  }'

Try It: Generate an API Key

Enter your email to get a live API key right now.

Save this key now. It won't be shown again.

Key ID:

Authentication

All escrow endpoints require an API key passed in the X-API-Key header. Key management endpoints (/api/keys) are public.

API Key Format: Keys start with cpk_live_ followed by 48 hex characters. Example: cpk_live_a1b2c3d4e5f6...

# Every request to /api/escrow/* must include:
X-API-Key: cpk_live_your_key_here

Protected endpoints (require X-API-Key):

MethodEndpointDescription
POST/api/escrowCreate escrow
GET/api/escrow/:idGet escrow details
POST/api/escrow/:id/settleSettle escrow

Public endpoints (no auth needed):

MethodEndpointDescription
POST/api/keysCreate API key
GET/api/keysList your keys
DELETE/api/keys/:key_idRevoke a key
POST/api/keys/:key_id/rotateRotate a key

Rate Limits

Each API key has independent rate limits. Default limits:

LimitDefaultHeader
Per minute60 requestsX-RateLimit-Limit
Per day10,000 requests-
Remaining-X-RateLimit-Remaining

When rate limited, responses include a Retry-After header (in seconds). Response code: 429.

Create API Key

POST /api/keys

Generate a new API key. Maximum 5 active keys per email.

REQUEST BODY

FieldTypeRequiredDescription
emailstringYesYour email address
namestringNoHuman-readable label (default: "Default")
curl -X POST https://clearpact.polsia.app/api/keys \
  -H "Content-Type: application/json" \
  -d '{"email": "dev@example.com", "name": "Production"}'
const res = await fetch("https://clearpact.polsia.app/api/keys", {
  method: "POST",
  headers: { "Content-Type": "application/json" },
  body: JSON.stringify({
    email: "dev@example.com",
    name: "Production"
  })
});
const { key } = await res.json();
console.log("Save this key:", key);
import requests

res = requests.post("https://clearpact.polsia.app/api/keys", json={
    "email": "dev@example.com",
    "name": "Production"
})
data = res.json()
print(f"Save this key: {data['key']}")

RESPONSE (201)

{
  "success": true,
  "message": "API key created. Save it now — it won't be shown again.",
  "key": "cpk_live_a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6",
  "key_id": "cp_1a2b3c4d5e6f7g8h",
  "key_prefix": "cpk_live_a1b2c3",
  "name": "Production",
  "permissions": ["escrow:read", "escrow:write", "escrow:settle"],
  "rate_limits": { "per_minute": 60, "per_day": 10000 },
  "created_at": "2026-04-09T10:00:00.000Z"
}

List API Keys

GET /api/keys?email=you@example.com

List all API keys associated with your email. Keys are returned without the secret value.

curl "https://clearpact.polsia.app/api/keys?email=dev@example.com"
const res = await fetch(
  "https://clearpact.polsia.app/api/keys?email=dev@example.com"
);
const { keys } = await res.json();
res = requests.get("https://clearpact.polsia.app/api/keys", params={
    "email": "dev@example.com"
})
keys = res.json()["keys"]

RESPONSE (200)

{
  "success": true,
  "keys": [
    {
      "key_id": "cp_1a2b3c4d5e6f7g8h",
      "key_prefix": "cpk_live_a1b2c3",
      "name": "Production",
      "is_active": true,
      "last_used_at": "2026-04-09T10:30:00.000Z",
      "requests_today": 42,
      "created_at": "2026-04-09T10:00:00.000Z"
    }
  ],
  "count": 1
}

Revoke API Key

DELETE /api/keys/:key_id

Immediately revoke an API key. All future requests with this key will be rejected.

curl -X DELETE https://clearpact.polsia.app/api/keys/cp_1a2b3c4d5e6f7g8h \
  -H "Content-Type: application/json" \
  -d '{"email": "dev@example.com"}'
await fetch("https://clearpact.polsia.app/api/keys/cp_1a2b3c4d5e6f7g8h", {
  method: "DELETE",
  headers: { "Content-Type": "application/json" },
  body: JSON.stringify({ email: "dev@example.com" })
});

Rotate API Key

POST /api/keys/:key_id/rotate

Revoke the old key and generate a new one with the same settings. Zero-downtime key rotation.

curl -X POST https://clearpact.polsia.app/api/keys/cp_1a2b3c4d5e6f7g8h/rotate \
  -H "Content-Type: application/json" \
  -d '{"email": "dev@example.com"}'
const res = await fetch(
  "https://clearpact.polsia.app/api/keys/cp_1a2b3c4d5e6f7g8h/rotate",
  {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify({ email: "dev@example.com" })
  }
);
const { key } = await res.json();
// Update your config with the new key

Create Escrow

POST /api/escrow

Create a new escrow contract between two parties. Requires X-API-Key header.

REQUEST BODY

FieldTypeRequiredDescription
payerstringYesPayer wallet address or identifier
payeestringYesPayee wallet address or identifier
amountstring/numberYesAmount in token units (e.g. "250.00")
tokenstringNoToken symbol (default: "USDC")
conditionsarrayNoSettlement conditions (see Condition Types)
metadataobjectNoArbitrary metadata (project name, etc.)
expires_atstringNoISO 8601 expiration timestamp
curl -X POST https://clearpact.polsia.app/api/escrow \
  -H "Content-Type: application/json" \
  -H "X-API-Key: cpk_live_YOUR_KEY" \
  -d '{
    "payer": "0xAlice",
    "payee": "0xBob",
    "amount": "500.00",
    "token": "USDC",
    "conditions": [
      {"type": "task_completion", "description": "Ship v2.0 release"},
      {"type": "approval", "approver": "0xAlice"}
    ],
    "metadata": {"project": "agent-audit"},
    "expires_at": "2026-12-31T00:00:00Z"
  }'
const res = await fetch("https://clearpact.polsia.app/api/escrow", {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
    "X-API-Key": "cpk_live_YOUR_KEY"
  },
  body: JSON.stringify({
    payer: "0xAlice",
    payee: "0xBob",
    amount: "500.00",
    conditions: [
      { type: "task_completion", description: "Ship v2.0" },
      { type: "approval", approver: "0xAlice" }
    ]
  })
});

const { escrow } = await res.json();
console.log("Escrow ID:", escrow.id);
import requests

res = requests.post(
    "https://clearpact.polsia.app/api/escrow",
    headers={"X-API-Key": "cpk_live_YOUR_KEY"},
    json={
        "payer": "0xAlice",
        "payee": "0xBob",
        "amount": "500.00",
        "conditions": [
            {"type": "task_completion", "description": "Ship v2.0"}
        ]
    }
)
escrow = res.json()["escrow"]
print(f"Escrow ID: {escrow['id']}")

RESPONSE (201)

{
  "success": true,
  "escrow": {
    "id": "550e8400-e29b-41d4-a716-446655440000",
    "payer": "0xAlice",
    "payee": "0xBob",
    "amount": 500,
    "token": "USDC",
    "status": "pending",
    "conditions": [
      {"type": "task_completion", "description": "Ship v2.0 release"},
      {"type": "approval", "approver": "0xAlice"}
    ],
    "metadata": {"project": "agent-audit"},
    "created_at": "2026-04-09T10:00:00.000Z",
    "expires_at": "2026-12-31T00:00:00.000Z"
  }
}

If conditions is empty or not provided, the escrow status starts as "active" instead of "pending".

Get Escrow

GET /api/escrow/:id

Retrieve escrow details and full event audit trail.

curl https://clearpact.polsia.app/api/escrow/550e8400-e29b-41d4-a716-446655440000 \
  -H "X-API-Key: cpk_live_YOUR_KEY"
const res = await fetch(
  "https://clearpact.polsia.app/api/escrow/550e8400-...",
  { headers: { "X-API-Key": "cpk_live_YOUR_KEY" } }
);
const { escrow, events } = await res.json();
res = requests.get(
    "https://clearpact.polsia.app/api/escrow/550e8400-...",
    headers={"X-API-Key": "cpk_live_YOUR_KEY"}
)
data = res.json()

RESPONSE (200)

{
  "success": true,
  "escrow": { /* full escrow object */ },
  "events": [
    {
      "event_type": "created",
      "actor": "0xAlice",
      "details": {"amount": 500, "token": "USDC"},
      "created_at": "2026-04-09T10:00:00.000Z"
    }
  ]
}

Settle Escrow

POST /api/escrow/:id/settle

Verify all conditions and release funds. All conditions must be met for settlement.

REQUEST BODY

FieldTypeRequiredDescription
verificationsobjectYesMap of condition index to verification data
actorstringNoWho is triggering the settlement
curl -X POST https://clearpact.polsia.app/api/escrow/ESCROW_ID/settle \
  -H "Content-Type: application/json" \
  -H "X-API-Key: cpk_live_YOUR_KEY" \
  -d '{
    "verifications": {
      "0": {"completed": true},
      "1": {"approved": true, "approver": "0xAlice"}
    },
    "actor": "0xOracle"
  }'
const res = await fetch(
  `https://clearpact.polsia.app/api/escrow/${escrowId}/settle`,
  {
    method: "POST",
    headers: {
      "Content-Type": "application/json",
      "X-API-Key": "cpk_live_YOUR_KEY"
    },
    body: JSON.stringify({
      verifications: {
        "0": { completed: true },
        "1": { approved: true, approver: "0xAlice" }
      },
      actor: "0xOracle"
    })
  }
);

const { settlement } = await res.json();
console.log("Settled:", settlement.amount, settlement.token);
res = requests.post(
    f"https://clearpact.polsia.app/api/escrow/{escrow_id}/settle",
    headers={"X-API-Key": "cpk_live_YOUR_KEY"},
    json={
        "verifications": {
            "0": {"completed": True},
            "1": {"approved": True, "approver": "0xAlice"}
        },
        "actor": "0xOracle"
    }
)
settlement = res.json()["settlement"]

RESPONSE — SUCCESS (200)

{
  "success": true,
  "message": "Escrow settled. 500 USDC released to 0xBob",
  "escrow": { "status": "settled", /* ... */ },
  "settlement": {
    "amount": 500,
    "token": "USDC",
    "from": "0xAlice",
    "to": "0xBob",
    "conditions": [
      {"index": 0, "type": "task_completion", "met": true},
      {"index": 1, "type": "approval", "met": true}
    ],
    "settled_at": "2026-04-09T12:00:00.000Z"
  }
}

RESPONSE — CONDITIONS NOT MET (422)

{
  "success": false,
  "message": "Not all conditions are met",
  "conditions": [
    {"index": 0, "type": "task_completion", "met": true},
    {"index": 1, "type": "approval", "met": false}
  ]
}

Condition Types

Conditions define what must be true before funds are released. Each escrow can have multiple conditions — all must be met for settlement.

task_completion

Requires explicit confirmation that work is done.

Condition: {"type": "task_completion"}

Verification: {"completed": true}

approval

Requires sign-off from a specific approver address.

Condition: {"type": "approval", "approver": "0x..."}

Verification: {"approved": true, "approver": "0x..."}

deadline

Automatically met if current time is before the deadline.

Condition: {"type": "deadline", "deadline": "2026-12-31T..."}

Verification: None needed (auto-checked)

threshold

A numeric value must meet or exceed a minimum.

Condition: {"type": "threshold", "min_value": 100}

Verification: {"value": 150}

oracle

An external oracle must confirm the outcome.

Condition: {"type": "oracle"}

Verification: {"oracle_confirmed": true}

custom

Any custom condition type. Requires explicit met flag.

Condition: {"type": "my_custom_check"}

Verification: {"met": true}

Error Codes

All errors return JSON with success: false and a descriptive error code.

HTTPError CodeDescription
400invalid_emailEmail is missing or malformed
400invalid_escrow_idEscrow ID is not a valid UUID
401missing_api_keyX-API-Key header not provided
401invalid_api_keyAPI key not recognized
401invalid_api_key_formatKey doesn't match cpk_ format
401api_key_revokedKey has been revoked
401api_key_expiredKey has expired
404escrow_not_foundNo escrow with that ID
404key_not_foundAPI key not found or already revoked
409already_settledEscrow is already settled/expired/cancelled
422conditions_not_metNot all conditions verified — includes details per condition
429rate_limit_exceededToo many requests per minute
429daily_limit_exceededDaily request limit reached

ERROR RESPONSE FORMAT

{
  "success": false,
  "error": "missing_api_key",
  "message": "API key required. Pass your key in the X-API-Key header.",
  "docs": "https://clearpact.polsia.app/docs#authentication"
}

Escrow Status Values

StatusDescriptionCan Settle?
pendingCreated with conditions, waiting for verificationYes
activeCreated without conditions, funds are lockedYes
settledAll conditions met, funds released to payeeNo
expiredPassed expires_at timestamp without settlementNo
cancelledCancelled before settlementNo