API docs

The API is plain JSON over HTTPS. Base URL:

Authentication

Sign in on the site with your wallet, open Account → API keys, and create a key. Send it as a bearer token:

Authorization: Bearer gf_live_xxxxxxxxxxxxxxxx

Tasks created with a key belong to the wallet that made the key. Payments still come from that wallet, so the API can post and approve, and you pay on the task page (or build the transaction yourself, see payment details). Reading tasks doesn't need a key.

Errors

Errors come back with a 4xx or 5xx status and a body like {"error":"Title is required"}.

POST/api/tasks

Create a task. Needs a key.

FieldTypeNotes
titlestringUp to 120 characters.
descriptionstringUp to 4000 characters. Say what a good result looks like.
categorystringsurvey, translation, data-labeling, verification, transcription, research, other
rewardnumberPer person, in whole tokens (e.g. 1.5).
tokenstringSOL or USDC
slotsintegerHow many people can take it. 1 to 500.
deadlinestring or numberISO date or Unix ms. At least 10 minutes out, at most 180 days.
curl -X POST /api/tasks \
  -H "Authorization: Bearer $API_KEY" -H "Content-Type: application/json" \
  -d '{"title":"Translate 3 lines to German","description":"...","category":"translation","reward":2,"token":"USDC","slots":1,"deadline":"2026-12-01T00:00:00Z"}'
201 Created
{"task":{"id":"tsk_9f2c...","owner":"YourWallet...","via":"api","title":"Translate 3 lines to German",
  "category":"translation","reward":2,"token":"USDC","slots":1,"filled":0,"slots_left":1,
  "status":"open","deadline":1764547200000,"created":1761400000000}}
GET/api/tasks

List tasks. Public. Query params, all optional:

statusopen (default), in_progress, done, closed, cancelled, or all
category, tokenFilter by category or token.
ownerOnly tasks posted by this wallet.
qText search in title and description.
sortnewest, reward, deadline
limit, offsetPaging. Limit up to 100, default 50.
curl "/api/tasks?category=verification&token=USDC"
{"tasks":[...],"total":0,"limit":50,"offset":0}
GET/api/tasks/:id

One task. If you send the owner's key, the response also has submissions, each with id, worker, payout, status (accepted, submitted, approved, paid, rejected) and result.

curl /api/tasks/tsk_9f2c... -H "Authorization: Bearer $API_KEY"
POST/api/submissions/:id/approve

Approve a submitted result. Needs the owner's key. Status moves from submitted to approved, and the work is ready to be paid.

curl -X POST /api/submissions/sub_41aa.../approve -H "Authorization: Bearer $API_KEY"
{"submission":{"id":"sub_41aa...","status":"approved",...},"next":"GET /api/submissions/sub_41aa.../payment"}
POST/api/submissions/:id/reject

Decline a result. Optional body {"note":"why"}. The spot opens up again.

GET/api/submissions/:id/payment

Exactly what to send. Amounts are in base units (lamports for SOL, 6 decimals for USDC). Put both transfers in one transaction signed by the payer wallet.

{"submission_id":"sub_41aa...","token":"USDC","mint":"EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
 "payer":"YourWallet...","fee_bps":,
 "transfers":[{"to":"WorkerPayout...","amount":2000000,"role":"worker"},
              {"to":"","amount":,"role":"platform_fee"}]}
POST/api/submissions/:id/pay

After the transaction confirms, send its signature. We fetch it from Solana and check that the payer signed it, it succeeded, and both transfers are at least the right amounts. Then the submission is marked paid. A signature can only be used once.

curl -X POST /api/submissions/sub_41aa.../pay \
  -H "Authorization: Bearer $API_KEY" -H "Content-Type: application/json" \
  -d '{"signature":"5h3k..."}'
POST/api/tasks/:id/cancel

Close a task so no one else can take it. Results already sent in can still be approved and paid.