View as Markdown
API reference
Base URL https://api.capless.sh. Every endpoint is under /v1 and takes authorization: Bearer cpl_… (except signup). The complete, machine-readable contract is the OpenAPI 3.1 spec: /openapi.yaml (also served at api.capless.sh/v1/openapi.yaml).
#Account
| Method | Path | |
POST | /v1/signup | Create user, project (trial), API key and optional site. No auth. Details |
#Streams
| Method | Path | |
POST | /v1/streams | Create a stream (name, optional validator) |
GET | /v1/streams | List streams, ordered by name |
GET | /v1/streams/{stream} | Metadata: head cursor, entryCount, lastCommittedAt, status |
PATCH | /v1/streams/{stream} | Rename and/or change the validator |
DELETE | /v1/streams/{stream} | Delete (asynchronous, 202) |
{stream} is the ID (str_…) or the name. Streams & cursors
#Entries
| Method | Path | |
POST | /v1/streams/{stream}/entries | Insert a batch atomically, idempotently |
POST | /v1/streams/{stream}/read | Read in cursor order with CEL filter/map |
POST | /v1/streams/{stream}/changes | Ordered feed of inserts and erasures |
POST | /v1/streams/{stream}/locate | Cursor for a commit time (index seek) |
Reading & change feed · Time seeking
#Erasures
| Method | Path | |
POST | /v1/streams/{stream}/erasures | Erase entries matching a CEL predicate (202) |
GET | /v1/streams/{stream}/erasures | List erasures in stream order |
GET | /v1/streams/{stream}/erasures/{erasure} | Status, progress, downstream propagation |
GET | /v1/streams/{stream}/erasures/{erasure}/entries | Exact affected entry IDs (once logically_applied) |
Erasures & GDPR
#Functions
| Method | Path | |
GET | /v1/functions | Describe the CEL environment |
POST | /v1/functions/evaluate | Evaluate an expression against a sample entry |
CEL functions
#Web analytics sites
| Method | Path | |
POST | /v1/web/sites | Create a site (name, allowedOrigins, replaySampleRate); returns key and snippet |
GET | /v1/web/sites | List sites |
PATCH | /v1/web/sites/{key} | Update a site |
DELETE | /v1/web/sites/{key} | Delete a site |
Web SDK
#Materializations
| Method | Path | |
POST | /v1/materializations | Create (name, type: "clickhouse") |
GET | /v1/materializations | List |
GET | /v1/materializations/{id} | Get |
DELETE | /v1/materializations/{id} | Delete with all its data (streams untouched) |
POST | /v1/materializations/{id}/query | Run one ClickHouse SQL statement |
POST | /v1/materializations/{id}/sources | Connect a stream to a table |
GET | /v1/materializations/{id}/sources | List sources with checkpoints |
DELETE | /v1/materializations/{id}/sources/{sourceId} | Detach a source |
GET | /v1/materializations/{id}/status | Insert and deletion freshness |
ClickHouse materializations
#Conventions
- Bodies are JSON, ≤ 8 MiB. Timestamps are UTC ISO 8601 with millisecond precision.
- Lists:
?limit= (1–1000, default 100) and ?pageToken= → {"data": [...], "nextPageToken": "…" | null}.
- Writes accept
idempotencyKey (kept 7 days).
#Errors
{ "error": { "code": "validation_failed", "message": "1 of 2 entries failed validation; nothing was committed.",
"details": { "failedCount": 1, "failures": [{ "index": 1, "message": "validator returned false" }] }, "requestId": "1b4e…" } }
| HTTP | Codes |
| 400 | invalid_json, invalid_request, invalid_name, invalid_expression, invalid_cursor, invalid_limit, invalid_timestamp, invalid_page_token, cursor_out_of_range, query_failed, unsupported_output_format, unsupported_type, project_required |
| 401 / 403 | unauthenticated, forbidden, query_forbidden |
| 404 | stream_not_found, erasure_not_found, materialization_not_found, source_not_found, site_not_found, route_not_found |
| 409 | stream_name_taken, materialization_name_taken, idempotency_key_reused, erasure_not_resolved, email_taken |
| 410 | stream_deleted |
| 413 | request_too_large, batch_too_large, entry_too_large |
| 422 | validation_failed, expression_evaluation_failed, result_too_large, limit_too_small, table_not_found, missing_lineage_column, unsupported_table_engine |
| 429 | rate_limited |
| 502 / 503 | engine_error, engine_unavailable, engine_unreachable |
Branch on code; messages are for humans and may change.