Developer API v1
Build with ground truth dataOne API key. Post tasks, poll for approved submissions, register webhooks. Integrate real-world data collection directly into your training pipeline.
AuthenticationEvery request must carry a bearer token in the Authorization header. Keys are per-organization, scoped, and revokable without touching your code.
API key formatKeys are prefixed gt_sk_ for easy scanning. The secret is shown exactly once at creation time and stored only as a bcrypt hash on our servers.
Per-key scopes (read / write / admin)
Last-used timestamp for audit
Instant revocation — no TTL wait
Rate limitsRate limits apply per API key and globally. Limits are returned in response headers so you can back off gracefully.
X-RateLimit-Limit
X-RateLimit-Remaining
X-RateLimit-Reset (Unix epoch)
Webhook deliveriesRegister an HTTPS endpoint and receive HMAC-signed events for every submission state change. Retried with exponential backoff.
submission.created
submission.approved
task.completed
EndpointsBase URL: https://groundtruth.io/api/v1
POST
/tasksCreate a new task and receive a funding link
GET
/tasksList tasks for your organization (paginated)
GET
/tasks/{id}Retrieve a single task with current status
GET
/tasks/{id}/submissionsStream approved submissions with signed media URLs
GET
/submissions/{id}Retrieve a submission and a short-lived download URL
POST
/webhook-endpointsRegister an HTTPS URL for event delivery
Create a taskPOST a task definition. The response includes a Stripe-hosted funding_url. Once funded, the task status transitions to open and contributors can begin submitting.
http
POST /api/v1/tasks
Authorization: Bearer gt_sk_••••••••
Content-Type: application/json

{
  "title": "Record a busy street scene",
  "instructions": "Walk any public street for 30 s. Steady hand, no filters.",
  "modalities": ["video"],
  "reward_cents": 250,
  "target_submissions": 100
}

// → 201 Created
{
  "id": "tsk_01hx4nvzgw5q9k3m",
  "status": "funding",
  "funding_url": "https://checkout.stripe.com/...",
  "reward_cents": 250,
  "target_submissions": 100,
  "created_at": "2026-06-18T14:32:00Z"
}
Fetch approved submissionsEach approved submission includes a short-lived signed URL (1 hour) for the raw media file. Paginate with next_cursor to stream all results.
http
GET /api/v1/tasks/tsk_01hx4nvzgw5q9k3m/submissions
Authorization: Bearer gt_sk_••••••••

// → 200 OK
{
  "data": [
    {
      "id": "sub_01hx7r4s2g0k1a5b",
      "status": "approved",
      "duration_seconds": 31,
      "media_url": "https://r2.groundtruth.io/sub_...?X-Amz-Expires=3600",
      "created_at": "2026-06-18T16:05:12Z"
    }
  ],
  "pagination": {
    "total": 47,
    "page": 1,
    "per_page": 20,
    "next_cursor": "cur_01hx7r4s2..."
  }
}
ErrorsAll errors follow a consistent structure with machine-readable codes so you can handle them programmatically without parsing messages.
json
{
  "error": {
    "code": "insufficient_budget",
    "message": "Task budget is below the minimum required to open.",
    "details": {
      "budget_cents": 1000,
      "required_cents": 2500
    }
  }
}
400validation_error
401unauthorized
403forbidden
404not_found
409conflict
429rate_limited
500internal_error
Coming soon
Full reference docs are on the wayWe're publishing a full OpenAPI spec with interactive examples, SDK quickstarts for Python and TypeScript, and a webhook testing console. Sign up now to get notified.