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"}.
/api/tasksCreate a task. Needs a key.
| Field | Type | Notes |
|---|---|---|
| title | string | Up to 120 characters. |
| description | string | Up to 4000 characters. Say what a good result looks like. |
| category | string | survey, translation, data-labeling, verification, transcription, research, other |
| reward | number | Per person, in whole tokens (e.g. 1.5). |
| token | string | SOL or USDC |
| slots | integer | How many people can take it. 1 to 500. |
| deadline | string or number | ISO 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}}
/api/tasksList tasks. Public. Query params, all optional:
| status | open (default), in_progress, done, closed, cancelled, or all |
| category, token | Filter by category or token. |
| owner | Only tasks posted by this wallet. |
| q | Text search in title and description. |
| sort | newest, reward, deadline |
| limit, offset | Paging. Limit up to 100, default 50. |
curl "/api/tasks?category=verification&token=USDC"
{"tasks":[...],"total":0,"limit":50,"offset":0}
/api/tasks/:idOne 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"
/api/submissions/:id/approveApprove 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"}
/api/submissions/:id/rejectDecline a result. Optional body {"note":"why"}. The spot opens up again.
/api/submissions/:id/paymentExactly 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"}]}
/api/submissions/:id/payAfter 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..."}'
/api/tasks/:id/cancelClose a task so no one else can take it. Results already sent in can still be approved and paid.