REST API

The 2Signal REST API is used by the Python SDK under the hood, but you can also call it directly for custom integrations in any language.

Base URL

https://api.2signal.dev/api/v1

Authentication

All endpoints (except health) require a project API key via the Authorization header:

Authorization: Bearer ts_your_api_key

API keys are project-scoped — each key belongs to a specific project. Create them in your project settings at app.2signal.dev, via the CLI, or TUI.

Quick Example

curl -X POST https://api.2signal.dev/api/v1/traces \
  -H "Authorization: Bearer ts_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{
    "batch": [
      {
        "id": "evt-1",
        "type": "trace-create",
        "body": {
          "id": "trace-1",
          "name": "my-agent"
        },
        "timestamp": "2026-03-14T10:00:00Z"
      }
    ]
  }'

Response Format

Success responses return data directly:

{ "accepted": 1 }

Error responses include a code and message:

{
  "error": {
    "code": "VALIDATION_ERROR",
    "message": "Invalid trace ID format"
  }
}

Status Codes

CodeMeaningWhen
200SuccessGET requests, model routing
201CreatedTraces and scores created
400Validation errorMalformed request body, missing fields
401UnauthorizedMissing, invalid, or revoked API key
404Not foundUnknown endpoint or resource
413Payload too largeBatch exceeds size limit
429Rate limitedToo many requests per second
500Server errorInternal error (retry with backoff)

Rate Limits

PlanRequests/sec
Free100
Pro1,000
Team1,000
Enterprise10,000

Rate limiting uses a sliding window per API key. When rate limited, the response includes:

HTTP/1.1 429 Too Many Requests
Retry-After: 1

{
  "error": {
    "code": "RATE_LIMIT_EXCEEDED",
    "message": "Rate limit exceeded. Retry after 1 second."
  }
}

Retry Strategy

Recommended retry behavior for production integrations:

  • 429 (rate limit) — wait for the Retry-After header duration, then retry
  • 500 / 502 / 503 — retry with exponential backoff (1s, 2s, 4s, max 3 retries)
  • 400 / 401 / 404 — do not retry (fix the request)

The Python SDK handles retries automatically.

Payload Limits

EndpointMax SizeMax Events
POST /traces5 MB1,000 events per batch
POST /otel/traces5 MB
POST /scores1 MB
POST /route-model512 KB

Timestamps

All timestamps use ISO 8601 format in UTC:

2026-03-14T10:30:00Z

The API accepts both Z and +00:00 suffixes.

Endpoints

MethodPathDescription
POST/api/v1/tracesBatch trace and span ingestion
POST/api/v1/otel/tracesOpenTelemetry OTLP/JSON trace ingestion
POST/api/v1/scoresSubmit evaluation scores
POST/api/v1/route-modelModel routing
GET/api/v1/prompt-templatesList templates or resolve by name/version
POST/api/v1/prompt-templatesCreate template or push new version
GET/api/v1/tracesQuery traces with filters
GET/api/v1/healthHealth check (no auth)

Health Check

curl https://api.2signal.dev/api/v1/health

# response:
{ "status": "ok" }

Have questions? Join our community!

Connect with other developers and the 2Signal team.

Join Discord