Skip to main content
The Relay API is organized around REST principles. It accepts JSON-encoded request bodies, returns JSON-encoded responses, and uses standard HTTP response codes.

Base URL

All API requests should be made to:
https://api.relayai.dev

Authentication

Authenticate requests by including your API key in the X-API-Key header:
curl https://api.relayai.dev/api/v1/datasets \
  -H "X-API-Key: your_api_key_here"
API keys are created in the Relay dashboard under Settings > API Keys.
Keep your API key secure. Do not share it in public repositories or client-side code.

Request format

  • Content-Type: application/json for all requests with a body
  • Method: Use appropriate HTTP methods (GET, POST, PATCH, DELETE)
  • IDs: All resource IDs are UUIDs
curl -X POST https://api.relayai.dev/api/v1/datasets \
  -H "X-API-Key: $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"name": "My Dataset", "artifact_types": [{"name": "glitch"}]}'

Response format

All responses are JSON-encoded. Successful responses include the requested resource or a confirmation.
{
  "id": "123e4567-e89b-12d3-a456-426614174000",
  "name": "My Dataset",
  "artifact_types": [{"name": "glitch"}],
  "created_at": "2024-01-15T10:30:00Z",
  "updated_at": "2024-01-15T10:30:00Z"
}

HTTP status codes

CodeDescription
200OK - Request succeeded
201Created - Resource created successfully
204No Content - Request succeeded (delete operations)
400Bad Request - Invalid request format
401Unauthorized - Invalid or missing API key
403Forbidden - Valid key but insufficient permissions
404Not Found - Resource doesn’t exist
422Validation Error - Request body validation failed
500Internal Server Error - Server-side error

Error responses

Errors return a JSON object with a detail field:
{
  "detail": "Dataset not found"
}
Validation errors (422) include details about which fields failed:
{
  "detail": [
    {
      "loc": ["body", "name"],
      "msg": "field required",
      "type": "value_error.missing"
    }
  ]
}

Pagination

List endpoints support pagination with page and page_size parameters:
curl "https://api.relayai.dev/api/v1/datasets/123/audio?page=1&page_size=50" \
  -H "X-API-Key: $API_KEY"
Paginated responses include:
{
  "items": [...],
  "total": 150,
  "page": 1,
  "page_size": 50,
  "has_more": true
}
FieldDescription
itemsArray of resources
totalTotal count across all pages
pageCurrent page number (1-indexed)
page_sizeItems per page
has_moreWhether more pages exist

Idempotency

POST requests that create resources are not idempotent. To avoid duplicates, track the returned id from successful requests.

Versioning

The API version is included in the URL path: /api/v1/... Breaking changes will be introduced in new versions (e.g., /api/v2/...). Existing versions remain supported.

Resource hierarchy

Tenant (your account)
├── Datasets
│   ├── Audio Files
│   └── Annotation Sets
│       └── Annotations
├── Training Jobs
├── Models
└── Inference Jobs
    └── Inference Files

Common patterns

Presigned URL uploads

Audio file uploads use presigned URLs for direct-to-storage uploads:
  1. Request URL: POST to get a presigned upload URL
  2. Upload: POST the file to the presigned URL
  3. Confirm: POST to confirm the upload completed
This keeps large files off the API servers and enables faster uploads.

Async operations

Training and inference are async operations:
  1. Create: POST to create a job
  2. Poll: GET the job periodically to check status
  3. Results: Read results when status is completed
while True:
    job = get_job(job_id)
    if job["status"] == "completed":
        break
    time.sleep(10)

Draft and publish

Annotation sets follow a draft → publish workflow:
  1. Create set (starts as draft)
  2. Add/edit annotations
  3. Publish (locks the set)
  4. Use for training

API endpoints