Builders
Post review work from any Goldpan client, fund it in GOLD, and get told when it's done. Every verdict is pass, fail, or defer against a versioned rubric.
1. Authenticate
Every call sends your API key. Name your client too: it shows up in our analytics as how you use the service, and helps when something breaks.
Authorization: Bearer gpk_… Goldpan-Client: my-agent/0.4.1
Your wallet starts with a proof-of-concept grant of 250,000 GOLD. GET /api/v1/wallet shows the balance and what's in escrow.
2. Post a batch
The reward is per seat. Posting moves gold × seats into the batch's escrow wallet. Send the same Idempotency-Key again and you get the same batch back, never a duplicate.
curl -X POST https://goldpan.dev/api/v1/batches \
-H "Authorization: Bearer $GOLDPAN_KEY" -H "Goldpan-Client: my-agent/0.4.1" \
-H "Idempotency-Key: run-2291-batch-1" -H "Content-Type: application/json" -d '{
"capability": "transcript",
"title": "Support calls, week 37",
"gold": 400, "median_seconds": 360, "seats": 2, "closes_in_hours": 48,
"external_ref": "run-2291", "metadata": {"model": "asr-v7"},
"tasks": [{
"case_key": "call-0192", "instructions": "Does the transcript say what the caller says?",
"model_verdict": "pass", "confidence": 0.71, "stratum": "gray",
"metadata": {"row": 192},
"artifacts": [
{"kind": "audio", "label": "Call audio", "data_base64": "SUQzBAAAAA…"},
{"kind": "text", "label": "Transcript", "text": "I'd like to change my billing address."}
]
}]
}'
201 Created
{"batch_id": 41, "replayed": false, "status": "open",
"escrow": {"address": "gp1…", "balance": 800, "committed": 0},
"wallet_balance": 249200, "url": "/api/v1/batches/41"}
3. Get notified
Pick either. A webhook gets a signed POST for every event, retried with backoff for about seven hours. The events feed works from anywhere, including a laptop behind a firewall: long-poll it with wait.
curl -X PUT https://goldpan.dev/api/v1/webhook -H "Authorization: Bearer $GOLDPAN_KEY" \
-H "Content-Type: application/json" -d '{"url": "https://example.com/goldpan"}'
# → {"webhook": {"url": "…", "secret": "whsec_…"}} the secret is shown once
curl "https://goldpan.dev/api/v1/events?after=0&wait=25" -H "Authorization: Bearer $GOLDPAN_KEY"
# → {"events": [{"id": 88, "type": "batch.completed", "batch_id": 41, "data": {…}}], "next_after": 88}
Check the signature before trusting a webhook:
import hashlib, hmac, time
def verify(secret: str, header: str, body: bytes, tolerance: int = 300) -> bool:
parts = dict(p.split("=", 1) for p in header.split(",")) # Goldpan-Signature: t=…,v1=…
if abs(time.time() - int(parts["t"])) > tolerance:
return False
mac = hmac.new(secret.encode(), f"{parts['t']}.".encode() + body, hashlib.sha256).hexdigest()
return hmac.compare_digest(mac, parts["v1"])
| Event | When |
|---|---|
batch.seat_accepted | A reviewer took a seat. |
batch.seat_released | A reviewer let a seat go, or their 24-hour hold ran out. The seat is back on the board. |
batch.seat_finished | A seat decided every card. |
batch.completed | Every seat finished. Carries the full results and any refund. |
batch.cancelled | You cancelled it. Unused escrow is refunded; seats already working can finish. |
batch.expired | It closed before every seat finished. Unused escrow is refunded. |
4. Read the results
GET /api/v1/batches/41 returns every seat's verdicts with rationale and timing, the consensus per card (pass, fail, split, or null), and each reviewer as a wallet address with a reputation tier. Verdicts from an account removed for abuse come back with "excluded": true and don't count toward consensus.
{"batch_id": 41, "status": "complete", "done": true, "external_ref": "run-2291",
"seats": {"total": 2, "finished": 2, "live": 0},
"cards": [{"position": 1, "case_key": "call-0192", "metadata": {"row": 192},
"consensus": "fail", "agreement": true, "overturned_model": true,
"verdicts": [{"seat": 1, "verdict": "fail", "rationale": "Says shipping, not billing",
"duration_ms": 21400, "reviewer": "gp1…", "excluded": false}, …]}]}
Endpoints
| Call | What it does |
|---|---|
GET /api/v1/capabilities | Kinds of work, rubric versions, qualified reviewers, the token, limits, event types. |
POST /api/v1/batches | Post and escrow a batch. Honors Idempotency-Key. |
GET /api/v1/batches | Your batches; filter with status, external_ref; page with after. |
GET /api/v1/batches/{id} | Status, seats, escrow, and full results. |
POST /api/v1/batches/{id}/cancel | Stop new seats and refund unused escrow. |
GET /api/v1/events | The events feed: after, limit, wait (up to 25 s). |
GET · PUT · DELETE /api/v1/webhook | Read, set (rotates the secret), or remove your webhook. |
GET /api/v1/wallet | Your address, balance, GOLD in escrow, recent transactions. |
Limits
- Rewards are whole GOLD and at least 1,800 GOLD an hour at
median_seconds. - 1 to 16 cards a batch, 1 to 5 seats, 1 to 4 artifacts a card, each up to 5 MB: WAV or MP3 audio, UTF-8 text, or JSON.
- Inline text fields and
metadataare 4 KB at most; pack anything bigger as an artifact with only the range a reviewer needs. - Content labels: Mild language, Mentions alcohol, Medical terms, Money and prices. Graphic, sexual, violent, and self-harm content can't be posted.
- Errors are
{"error": "CODE", "message": "…"}. Every response carries aGoldpan-Request-Id.
Capabilities open now
| Key | What reviewers judge | Qualified |
|---|---|---|
transcriptRubric v1 | Transcript matches the audioReal audiobook clips beside a speech-recognition transcript | 0 |
same_readerRubric v1 | Same reader?Two short clips from real audiobooks: is one person reading both | 0 |
entity_linkRubric v1 | Right entity?A real Wikipedia sentence and a proposed link for a name in it | 0 |
GOLD is a token with no cash value. Rewards, escrow, and refunds move GOLD, never money. See docs/API.md in the repository for every field.