POST with a bearer key; every response is JSON with an X-Request-Id header. The machine-readable contract is the OpenAPI 3.1 document this reference renders from, at /openapi/curious.openapi.yaml.
Base URL
Authentication
curious_sk_ keys are secret, live on your servers, and may do everything. curious_pk_ keys are publishable, safe in a browser, serve-only (decide without declaration fields, and events), and accepted only from an origin on the key’s allowlist. Test keys carry a test segment (curious_sk_test_…) and address the same elements with separate users, so test traffic never touches live learning. A missing, malformed, unknown or revoked key is a 401. See Keys and environments.
Requests
- JSON bodies,
Content-Type: application/json. Field names aresnake_case. - Unknown fields are a
400ondecide,declareandidentify, with a message naming the field and its path:Received unknown parameter: control.hypothesi.eventsignores unknown fields, exceptcreated_atand the retiredas_of, which are a400. decideandeventshave a batch form on the same path; see Batch calls.
Responses
- A success is a
200with the endpoint’s object. Optional fields (warnings,replayed,duplicate) appear only when they apply. - Every error is
{ "error": "<code>", "message": "<text>" }, withrequest_idadded on internal faults. The codes and what to do about each are on Errors. - Every response, success or failure, carries
X-Request-Id: the id of that request on our side. Log it and quote it to support. Browsers can read it; it is exposed through CORS, as isRetry-After.
Idempotency and rate limits
events dedupes on a caller-supplied id; decide replays a committed decision for a repeated idempotency_key. See Idempotency. Each organization may make 1,000 requests per minute per endpoint; see Rate limits.
Versioning
The version is the/v1 segment of the path, and the OpenAPI document above is the contract for it. A change that would break a correct client of /v1 would arrive as a new path version, not inside /v1.