Skip to content
Warrantv0.1

Quickstart

Open your first warrant in five minutes.

By the end of this page an agent will have paid an API only after the response passed a check you wrote.

npm i @warrant/sdk
export WARRANT_API_KEY=wr_test_...

1. Get a sandbox key

Keys are created in the console under Developer → API keys. A sandbox key is prefixed wr_test_ and can never move real money; see Sandbox vs production.

Keys belong to agents, not people. A key can open and verify warrants, and it deliberately cannot resolve an escalation — if a key could approve a payment, the approval step would be decorative.

2. Open a warrant

Amounts are strings, never JSON numbers

Every amount crossing the wire is a string of whole units of the asset's smallest denomination, in both directions. "8400000" is 8.40 USDC. The bare number 8400000 is rejected, and so is "8.40" — the field is validated against ^[0-9]+$, so there is no decimal point in it.

This is not a style preference. 9007199254740993 is a legal amount and is not representable as a JSON number, and a payments API that silently rounds is worse than one that refuses.

POST /v1/warrants HTTP/1.1
Host: api.gowarrant.xyz
Authorization: Bearer wr_test_...
Idempotency-Key: 8f0c1b4e-2b1a-4d59-9d0e-3a2f7c1b9e44
Content-Type: application/json

{
"amount": "8400000",
"asset": "USDC",
"payee": "api.exampledata.io",
"deadline": "2026-08-20T12:00:00.000Z",
"spec": {
  "clauses": [
    { "kind": "http.status", "equals": 200 },
    { "kind": "data.freshness", "maxAgeSeconds": 60 }
  ]
}
}

201

{
"id": "wr_01KZX3KD38A0253NGVXTC8K9MF",
"object": "warrant",
"state": "held",
"version": 1,
"amount": "8400000",
"asset": "USDC",
"released_bps": null,
"payee": "api.exampledata.io",
"spec_hash": "sha256:41f0...8ad2",
"deadline": "2026-08-20T12:00:00.000Z",
"opened_at": "2026-08-13T12:00:00.000Z",
"settled_at": null
}
curl -X POST https://api.gowarrant.xyz/v1/warrants \
-H "Authorization: Bearer $WARRANT_API_KEY" \
-H "Idempotency-Key: $(uuidgen)" \
-H "Content-Type: application/json" \
-d '{
  "amount": "8400000",
  "asset": "USDC",
  "payee": "api.exampledata.io",
  "deadline": "2026-08-20T12:00:00.000Z",
  "spec": { "clauses": [{ "kind": "http.status", "equals": 200 }] }
}'

The funds are now held. Nothing has been sent.

3. Verify the deliverable

Point the verifier at the thing you are paying for. It fetches the URL itself; the agent's own account of what happened is never the evidence.

POST /v1/warrants/wr_01KZX3KD38A0253NGVXTC8K9MF/verify HTTP/1.1
Authorization: Bearer wr_test_...
Idempotency-Key: 1c9d6a02-77f1-4e2c-9c33-9a1d0b6f2e77
Content-Type: application/json

{ "source_url": "https://api.exampledata.io/v2/invoice/8812" }

200

{
"id": "wr_01KZX3KD38A0253NGVXTC8K9MF",
"object": "warrant",
"state": "released",
"version": 3,
"amount": "8400000",
"released_bps": 10000,
"settled_at": "2026-08-13T12:00:04.118Z"
}
curl -X POST https://api.gowarrant.xyz/v1/warrants/$ID/verify \
-H "Authorization: Bearer $WARRANT_API_KEY" \
-H "Idempotency-Key: $(uuidgen)" \
-H "Content-Type: application/json" \
-d '{ "source_url": "https://api.exampledata.io/v2/invoice/8812" }'

released_bps is basis points of the held amount, so 10000 is all of it.

Had a clause failed, the state would be escalated and the amount would still be held, waiting on a person. That is the interesting path, and Escalations covers it.

4. Read the trace

Every settled warrant has a receipt at GET /t/:id, and that route needs no key at all. It is the link you send the other side when they ask why they were not paid.

Next