Logs API

Ingest log events and search through your logs using DSL queries.

POST
/functions/v1/ingest
Ingest log events into the system. Events are queued and processed asynchronously.

Authentication

Requires JWT token (Bearer token) or API key (X-API-Key header or Bearer with ll_ prefix)

Parameters

NameTypeRequiredDescription
logsLogEvent[] | LogEventRequiredArray of log events or a single log event object

Request Body

interface LogEvent {
  ts?: string | number;  // ISO 8601 timestamp or Unix timestamp
  level?: 'debug' | 'info' | 'warn' | 'error';
  msg?: string;
  service?: string;
  env?: string;
  req_id?: string;
  user_id?: string;
  route?: string;
  host?: string;
  attrs?: Record<string, any>;  // Additional attributes as JSON
}
Example
[
  {
    "ts": "2025-01-15T10:30:00Z",
    "level": "info",
    "msg": "User logged in",
    "service": "api",
    "user_id": "user-123",
    "route": "/api/auth/login"
  },
  {
    "ts": "2025-01-15T10:30:05Z",
    "level": "error",
    "msg": "Payment failed",
    "service": "payment",
    "req_id": "req-456",
    "attrs": {
      "amount": 100.00,
      "currency": "USD"
    }
  }
]

Responses

200Successfully queued log events
{
  "success": true,
  "ingested": 2,
  "rejected": 0
}
400Invalid request (invalid JSON, too many records, etc.)
{
  "error": "Too many records: 15000 (max 10000)"
}
401Authentication failed
{
  "error": "Invalid token, API key, or missing tenant_id"
}
413Request body too large
{
  "error": "Request body too large: 600000 bytes (max 512000)"
}

Examples

curl -X POST https://your-project.supabase.co/functions/v1/ingest \
  -H "Authorization: Bearer YOUR_JWT_TOKEN" \
  -H "Content-Type: application/json" \
  -d '[
    {
      "ts": "2025-01-15T10:30:00Z",
      "level": "info",
      "msg": "User logged in",
      "service": "api"
    }
  ]'

Limits

  • Maximum 10,000 records per request
  • Maximum 500KB request body size
  • Events are queued and processed asynchronously
  • Timestamps are automatically added if missing
POST
/functions/v1/search-dsl
Search logs using DSL (Domain-Specific Language) queries. Supports complex filtering, full-text search, and pagination.

Authentication

Requires JWT token (Bearer token)

Parameters

NameTypeRequiredDescription
tenantIdstringRequiredTenant ID (extracted from JWT if not provided)
tsFromstringRequiredStart timestamp (ISO 8601 format)
tsTostringRequiredEnd timestamp (ISO 8601 format)
querystringOptionalDSL query string (e.g., "level = 'error' AND service = 'api'")
limitnumberOptionalMaximum number of results (default: 100, max: 1000)
afterstringOptionalPagination token from previous response

Request Body

interface SearchRequest {
  tenantId: string;
  tsFrom: string;  // ISO 8601
  tsTo: string;    // ISO 8601
  query?: string;  // DSL query
  limit?: number;  // 1-1000, default 100
  after?: string; // Pagination token
}
Example
{
  "tenantId": "tenant-123",
  "tsFrom": "2025-01-15T00:00:00Z",
  "tsTo": "2025-01-15T23:59:59Z",
  "query": "level = 'error' AND service = 'api'",
  "limit": 100
}

Responses

200Search results
{
  "data": [
    {
      "id": "uuid",
      "ts": "2025-01-15T10:30:00Z",
      "level": "error",
      "msg": "Payment failed",
      "service": "api",
      "tenant_id": "tenant-123",
      "attrs": {}
    }
  ],
  "pagination": {
    "limit": 100,
    "hasMore": true,
    "nextAfter": "base64-encoded-token"
  },
  "meta": {
    "totalMatched": 1234,
    "queryTimeMs": 45
  }
}
400Invalid request parameters
{
  "error": "Time range cannot exceed 30 days"
}
401Authentication failed
{
  "error": "Missing authorization header"
}

Examples

curl -X POST https://your-project.supabase.co/functions/v1/search-dsl \
  -H "Authorization: Bearer YOUR_JWT_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "tenantId": "tenant-123",
    "tsFrom": "2025-01-15T00:00:00Z",
    "tsTo": "2025-01-15T23:59:59Z",
    "query": "level = '''error''' AND service = '''api'''",
    "limit": 100
  }'

DSL Query Language

The search endpoint supports a powerful DSL for querying logs. Learn more about DSL syntax in the DSL Query Language documentation.

Example Queries

// Simple equality
"level = 'error'"

// Multiple conditions
"level = 'error' AND service = 'api'"

// OR logic
"level IN ('error', 'warn') OR service = 'worker'"

// Full-text search
"msg CONTAINS 'payment failed'"

// JSONB fields
"attrs.status = 500"

// Pattern matching
"msg LIKE '%timeout%'"

Pagination

The search endpoint uses keyset pagination for efficient large result sets. Use the nextAfter token from the response to fetch the next page.

// First request
const response1 = await fetch('/functions/v1/search-dsl', {
  method: 'POST',
  body: JSON.stringify({
    tenantId: 'tenant-123',
    tsFrom: '2025-01-15T00:00:00Z',
    tsTo: '2025-01-15T23:59:59Z',
    limit: 100
  })
})

const data1 = await response1.json()

// Next page
if (data1.pagination.hasMore) {
  const response2 = await fetch('/functions/v1/search-dsl', {
    method: 'POST',
    body: JSON.stringify({
      tenantId: 'tenant-123',
      tsFrom: '2025-01-15T00:00:00Z',
      tsTo: '2025-01-15T23:59:59Z',
      limit: 100,
      after: data1.pagination.nextAfter
    })
  })
}