API Reference
Streaming
Browser access to the WebSocket stream without an API key in the browser.
Read from the running API at , version 1.0.0, and read again every 5 minutes.
Every endpoint here authenticates with X-API-Key, answers in the standard envelope and fails with the standard error body.
Issue a single-use stream ticket for a browser
https://api.cantoncap.cc/v1/stream/ticketsCall this from your server, never from a browser. The ticket opens one WebSocket stream from one web origin, so a browser can stream without holding your API key. Pass it to the page, which opens wss://api.cantoncap.cc/v1/stream offering the subprotocols cantoncap.v1 and cantoncap.ticket.<ticket>; the gateway answers with cantoncap.v1. Never put a ticket in a URL: a handshake that carries one in its query string is refused and the ticket is used up. A ticket is bound to this key, its account and plan, and the origin given here; it is redeemed once, and expires 30 seconds after issue. Redemption re-checks the account and takes one of its stream connections, and counts toward its minute limit. Plans without streaming are refused with 403 plan_not_authorized. Issuing a ticket counts toward the minute limit.
Credits: 0 credits.
Parameters
This endpoint takes no parameters.
Request Body
{
"origin": "https://app.example.com"
}originstringThe web origin of the page that will open the stream: an https origin, or http on localhost, 127.0.0.1 or [::1], written exactly as a browser sends it in Origin (scheme and host, an optional non-default port, no path or trailing slash).
Request
curl -s -X POST "https://api.cantoncap.cc/v1/stream/tickets" \
-H "X-API-Key: $CANTONCAP_API_KEY" \
-H "Content-Type: application/json" \
-d '{"origin":"https://app.example.com"}'Response
200 A ticket redeemable once, from the given origin, until expires_at.
{
"status": {
"timestamp": "2026-10-11T14:00:00.000Z",
"elapsed_ms": 18,
"error_code": 0,
"error_message": null,
"request_id": "req_7Hk2pQ9xLm"
},
"data": {
"ticket": "cst_Xq8vN2cTf0LmZ7rKpA4sWb1hYe9uJd3gQo6iVxC5nRt",
"origin": "https://app.example.com",
"expires_at": "2026-10-11T14:00:30.000Z"
}
}dataobject3 child fields
ticketstringOpaque single-use ticket. Treat it as a secret until it is redeemed.
originstringThe origin the ticket is bound to.
expires_atdate-timeWhen the ticket stops being redeemable, at most 30 seconds after issue.
Headers
X-RateLimit-LimitMaximum requests admitted in the current plan window, which every key of an account shares.X-RateLimit-RemainingRequests remaining in the current plan window, across every key of the account.X-RateLimit-ResetUnix timestamp in seconds when the current plan window resets.Cache-Controlprivate, no-store Prevents every cache, private or shared, from storing the response. Every error response carries it.
Errors
| Status | Code | When | error_code today | From launch |
|---|---|---|---|---|
| 400 | invalid_request | A parameter, body or cursor is invalid. | 1000 | 400 |
| 401 | unauthenticated | The X-API-Key header is missing or empty. | 1001 | 1002 |
| 401 | unauthenticated | The API key is unknown, malformed or deleted. | 1001 | 1001 |
| 402 | payment_required | The account is not activated. | 402 | 1003 |
| 402 | payment_required | The account's paid period has ended unpaid. | 402 | 1004 |
| 403 | forbidden | The API key is disabled or does not resolve to an active plan. | 1002 | 1007 |
| 403 | forbidden | The API key's account is suspended. | 1002 | 1007 |
| 403 | forbidden | The API key lacks a permission the operation needs. | 1002 | 1006 |
| 403 | plan_not_authorized | The API plan does not include the operation. | 403 | 1006 |
| 403 | quota_exceeded | The requested history or page size exceeds the API plan. | 1006 | 1006 |
| 404 | not_found | The resource does not exist or is not published. | 1003 | 404 |
| 429 | rate_limited | The account's per-minute request limit is used up. | 1005 | 1008 |
| 429 | credit_limit_reached | The account's monthly credits are used up. | 429 | 1010 |
| 429 | ip_rate_limited | Too many requests without a valid API key came from this address. | 429 | 1011 |
| 500 | internal_error | The server failed unexpectedly. | 1009 | 500 |
| 503 | source_unavailable | A data or quota store is unavailable, or the service is at capacity. | 1008 | 503 |