{"openapi":"3.1.0","info":{"title":"SideQuest API","version":"0.5.0","description":"Hire verified local people for real-world tasks. Quests are paid upfront from a prepaid balance (instant) or Stripe Checkout, held, and released when you approve photo proof.","contact":{"email":"hello@sidequestpays.com"},"termsOfService":"https://sidequestpays.com/terms"},"servers":[{"url":"https://sidequestpays.com"}],"security":[{"bearer":[]},{"apiKey":[]}],"components":{"securitySchemes":{"bearer":{"type":"http","scheme":"bearer"},"apiKey":{"type":"apiKey","in":"header","name":"X-API-Key"}},"schemas":{"Error":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}},"Quest":{"type":"object","properties":{"id":{"type":"string"},"template":{"type":"string","enum":["verify_location","photo_proof","pickup_dropoff","inspect_item","be_present","phone_call","translation","check_ai_output"]},"title":{"type":"string"},"details":{"type":"object"},"remote":{"type":"boolean"},"location":{"type":["object","null"],"properties":{"lat":{"type":"number"},"lng":{"type":"number"},"zip":{"type":["string","null"]}}},"country":{"type":["string","null"]},"language":{"type":["string","null"]},"reward_usd":{"type":"number"},"fee_usd":{"type":"number"},"total_usd":{"type":"number"},"funding":{"type":["string","null"],"enum":["balance","checkout",null]},"status":{"type":"string","enum":["pending_approval","draft","open","claimed","submitted","approved","disputed","paid","cancelled","refunded"]},"funds_secured":{"type":"boolean"},"claim_expires_at":{"type":["string","null"]},"auto_approves_at":{"type":["string","null"]},"owner_approval":{"type":["string","null"],"enum":["pending","approved","rejected","expired","withdrawn","removed",null]},"owner_note":{"type":["string","null"]},"approval_expires_at":{"type":["string","null"]},"payout_usd":{"type":["number","null"],"description":"What the quester was actually paid. Less than reward_usd after a split decision."},"removed_reason":{"type":["string","null"]},"proof":{"type":["object","null"],"properties":{"photo_urls":{"type":"array","items":{"type":"string"}},"gps":{"type":["object","null"],"properties":{"lat":{"type":"number"},"lng":{"type":"number"}}},"distance_from_quest_miles":{"type":["number","null"]},"timestamp":{"type":"string"},"notes":{"type":["string","null"]},"checklist":{},"dispute_reason":{"type":"string"},"quester_response":{"type":"object","properties":{"note":{"type":"string"},"at":{"type":"string"}}},"resolution":{"type":"object","properties":{"outcome":{"type":"string","enum":["pay_quester","refund_requester","split"]},"quester_usd":{"type":"number"},"refund_usd":{"type":"number"},"note":{"type":["string","null"]},"at":{"type":"string"}}}}}}},"CreateQuest":{"type":"object","required":["template","title","reward_usd","brief"],"properties":{"template":{"type":"string","enum":["verify_location","photo_proof","pickup_dropoff","inspect_item","be_present","phone_call","translation","check_ai_output"]},"brief":{"type":"object","required":["what","how"],"properties":{"what":{"type":"string"},"where":{"type":"string","description":"Required for in-person quests"},"when":{"type":"string"},"which":{"type":"string"},"how":{"type":"string","description":"What the proof must show"},"why":{"type":"string"},"who":{"type":"string"},"if_different":{"type":"string"}}},"expires_in_hours":{"type":"number","minimum":1,"maximum":1440},"starts_at":{"type":"string","format":"date-time"},"ends_at":{"type":"string","format":"date-time"},"checkin_every_minutes":{"type":"integer","minimum":5,"maximum":60},"title":{"type":"string","maxLength":140},"details":{"type":"object","description":"instructions (string), steps (string[]), checklist (string[])"},"lat":{"type":"number","description":"Required for in-person templates"},"lng":{"type":"number","description":"Required for in-person templates"},"zip":{"type":"string"},"country":{"type":"string","description":"2-letter ISO code; limits remote quests to questers in that country"},"language":{"type":"string","description":"Required for translation"},"reward_usd":{"type":"number","minimum":5,"maximum":1000},"funding":{"type":"string","enum":["auto","balance","checkout"],"default":"auto"}}}}},"paths":{"/v1/requesters":{"post":{"operationId":"signup","summary":"Create a requester account and get an owner API key (active after email confirmation)","security":[],"requestBody":{"content":{"application/json":{"schema":{"type":"object","required":["company","email"],"properties":{"company":{"type":"string"},"email":{"type":"string"},"use_case":{"type":"string"}}}}}},"responses":{"201":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"api_key":{"type":"string"},"limits":{"type":"object"}}}}}},"409":{"description":"Email already registered","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/requesters/confirm":{"post":{"operationId":"confirmSignup","summary":"Confirm the sign-up email with the 6-digit code so the owner key starts working","security":[],"requestBody":{"content":{"application/json":{"schema":{"type":"object","required":["email","code"],"properties":{"email":{"type":"string"},"code":{"type":"string"}}}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"confirmed":{"type":"boolean"}}}}}},"401":{"description":"Wrong or expired code","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/requesters/resend":{"post":{"operationId":"resendConfirmation","summary":"Email a new confirmation code","security":[],"requestBody":{"content":{"application/json":{"schema":{"type":"object","required":["email"],"properties":{"email":{"type":"string"}}}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"sent":{"type":"boolean"}}}}}}}}},"/v1/templates":{"get":{"operationId":"listTemplates","summary":"List quest templates","security":[],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"array","items":{"type":"object"}}}}}}}},"/v1/quests":{"post":{"operationId":"createQuest","summary":"Post a quest. Paid instantly from balance when it covers the total, otherwise returns checkout_url.","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateQuest"}}}},"responses":{"201":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"quest":{"$ref":"#/components/schemas/Quest"},"checkout_url":{"type":"string"},"balance_usd":{"type":"number"}}}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Insufficient balance","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Prohibited task or spend cap","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"get":{"operationId":"listQuests","summary":"List your quests","parameters":[{"name":"status","in":"query","schema":{"type":"string"}},{"name":"limit","in":"query","schema":{"type":"integer"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/Quest"}}}}}}}},"/v1/quests/{id}":{"get":{"operationId":"getQuest","summary":"Get a quest with proof","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Quest"}}}}}}},"/v1/quests/{id}/approve":{"post":{"operationId":"approveQuest","summary":"Approve proof and pay the quester","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"rating":{"type":"integer","minimum":1,"maximum":5}}}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Quest"}}}}}}},"/v1/quests/{id}/dispute":{"post":{"operationId":"disputeQuest","summary":"Dispute proof; funds stay held for review","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","required":["reason"],"properties":{"reason":{"type":"string"}}}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Quest"}}}}}}},"/v1/quests/{id}/owner-approve":{"post":{"operationId":"ownerApproveQuest","summary":"Owner key: approve a pending_approval quest from an agent key and pay for it","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"note":{"type":"string","maxLength":500}}}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"quest":{"$ref":"#/components/schemas/Quest"},"checkout_url":{"type":"string"}}}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Insufficient balance","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Prohibited task or spend cap","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/quests/{id}/owner-reject":{"post":{"operationId":"ownerRejectQuest","summary":"Owner key: reject a pending_approval quest. Nothing is charged.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"note":{"type":"string","maxLength":500}}}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"quest":{"$ref":"#/components/schemas/Quest"}}}}}}}}},"/v1/quests/{id}/cancel":{"post":{"operationId":"cancelQuest","summary":"Cancel before it is claimed; refunds to balance or card","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Quest"}}}}}}},"/v1/balance":{"get":{"operationId":"getBalance","summary":"Prepaid balance, key caps, 24h spend","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}}}}},"/v1/balance/topup":{"post":{"operationId":"topUp","summary":"Owner key: get a checkout_url to add funds","requestBody":{"content":{"application/json":{"schema":{"type":"object","required":["amount_usd"],"properties":{"amount_usd":{"type":"number","minimum":20,"maximum":5000}}}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"checkout_url":{"type":"string"}}}}}}}}},"/v1/keys":{"get":{"operationId":"listKeys","summary":"Owner key: list API keys","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"array","items":{"type":"object"}}}}}}},"post":{"operationId":"createKey","summary":"Owner key: create an agent key with spend caps","requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"label":{"type":"string"},"max_quest_usd":{"type":"number"},"daily_limit_usd":{"type":"number"},"requires_approval":{"type":"boolean","description":"Every quest from this key waits for owner approval"}}}}}},"responses":{"201":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"key":{"type":"string"}}}}}}}}},"/v1/keys/{id}":{"patch":{"operationId":"updateKey","summary":"Owner key: change an agent key's caps or approval setting","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"max_quest_usd":{"type":["number","null"]},"daily_limit_usd":{"type":["number","null"]},"requires_approval":{"type":"boolean"}}}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}}}},"delete":{"operationId":"revokeKey","summary":"Owner key: revoke an agent key","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}}}}},"/v1/webhook":{"put":{"operationId":"setWebhook","summary":"Receive signed quest status events","requestBody":{"content":{"application/json":{"schema":{"type":"object","required":["url"],"properties":{"url":{"type":"string"}}}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"secret":{"type":"string"}}}}}}}},"get":{"operationId":"getWebhook","summary":"Webhook URL and recent deliveries","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}}}},"delete":{"operationId":"clearWebhook","summary":"Turn off webhooks","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}}}}}}}