# Curious > Curious documentation: the API, the SDKs and the concepts behind autonomous experimentation. - [Introduction](https://docs.trycurious.ai/index.md): Curious runs experiments on your product's content: you name what to optimize and what success is; it writes the variants, tests them, and keeps the winners. - [Quickstart](https://docs.trycurious.ai/quickstart.md): Make your first decision and attribute your first reward in a few minutes with a test key, using the server SDK or plain HTTP. - [Keys and environments](https://docs.trycurious.ai/guides/keys.md): Secret versus publishable keys, test versus live environments, origin allowlists, and rotation. - [AI onboarding](https://docs.trycurious.ai/ai-onboarding.md): For AI coding agents integrating Curious: where the machine-readable documentation is, which surface to use, and the rules an integration must follow. - [Serve a decision](https://docs.trycurious.ai/guides/decide.md): Call decide to get the content to show a user: the minimum request, the user buckets, the declaration, the response, and what publishable keys may send. - [Track outcomes](https://docs.trycurious.ai/guides/events.md): Report what users did with POST /events: request and response, naming, timestamps, properties versus context, idempotent ids, and batches of up to 200. - [Fallbacks and timeouts](https://docs.trycurious.ai/guides/fallbacks.md): What a correct delivery path does when Curious is slow or down: a deadline on every decide, your control as the fallback, and no retries without a key. - [Identify users](https://docs.trycurious.ai/guides/identify.md): Link an anonymous user to a known one with POST /identify, update a known user's state, and handle login and logout correctly. - [Declare ahead of traffic](https://docs.trycurious.ai/guides/declare.md): Configure an element without serving anyone: the same declaration as decide, run from a setup script or deploy step, with no user and no decision. - [Batch calls](https://docs.trycurious.ai/guides/batch.md): Decide several elements or report several events in one request: envelopes, caps, per-item results and errors, and per-item idempotency. - [Test with test keys](https://docs.trycurious.ai/guides/testing.md): Run the whole loop on a test key before live traffic: what the test environment shares with live, what it keeps separate, and its use in staging and CI. - [Go-live checklist](https://docs.trycurious.ai/guides/go-live.md): What to confirm before switching from a test key to a live one: keys and origins, the declaration, the delivery path, events, identity, the first decision. - [SDK overview](https://docs.trycurious.ai/sdks/overview.md): Which package to use where: the server SDK for Node, Deno, Bun and edge runtimes, the browser SDK, and raw HTTP for everything else. - [Install and configure the server SDK](https://docs.trycurious.ai/sdks/node.md): @trycurious/node: the server SDK for Node, Deno, Bun, Cloudflare Workers and Supabase Edge Functions. Install it, construct a client, and tune its options. - [Decide with the server SDK](https://docs.trycurious.ai/sdks/node/decide.md): decide() and decideMany(): the required fallback, the deadline, the result, the camelCase declaration, idempotency keys, and the setting that makes it throw. - [Events and identify with the server SDK](https://docs.trycurious.ai/sdks/node/events.md): track(), flush() and trackNow() for event delivery, identify() for identity and declare() for configuration, with the lifecycle hook each runtime needs. - [Errors in the server SDK](https://docs.trycurious.ai/sdks/node/errors.md): The server SDK's error model: every stable code, what it means, whether it is retryable, where it surfaces, and how API statuses map onto it. - [Server SDK examples](https://docs.trycurious.ai/sdks/node/examples.md): Complete server SDK examples for Next.js, a Cloudflare Worker, a Supabase Edge Function and a Node job, each with a decision, an event and the right flush. - [Raw HTTP](https://docs.trycurious.ai/sdks/http.md): Use the API without an SDK: headers, the four calls, and everything the SDK would otherwise handle for you, so you can implement it in any language. - [The model](https://docs.trycurious.ai/concepts/model.md): The nouns behind the four endpoints, one line each with a link to its page: element, declaration, arm, user, decision, reward, constraint, event. - [Elements](https://docs.trycurious.ai/concepts/elements.md): An element is one piece of content Curious optimizes as a whole, named by you; what makes something one element or two, and what element_type does. - [Declarations](https://docs.trycurious.ai/concepts/declarations.md): A declaration is everything a secret-key call says about an element: the control, the arms, and which field changes start a new experiment. - [Users, identifiers and attributes](https://docs.trycurious.ai/concepts/users.md): Who a decision is made for: your user_id, the identifiers, attributes and context buckets, anonymous users, and how identify links them. - [Assignment and stickiness](https://docs.trycurious.ai/concepts/assignment.md): What a decision is, how an arm is chosen for a user, what static and dynamic assignment mean, the holdout cohort, and why every decide call creates a decision. - [Rewards](https://docs.trycurious.ai/concepts/rewards.md): Rewards are the events that define success: type, window, weight, properties filter, value source and baseline rate, and how they combine. - [Constraints](https://docs.trycurious.ai/concepts/constraints.md): Constraints are guardrails: an event rate a variant may not breach and stay live, relative to the control or absolute, changeable without a restart. - [Events and attribution](https://docs.trycurious.ai/concepts/events.md): An event is what a user did: how its name, properties, value and timestamp are read, and how it attributes to the decision before it. - [Variables and parameters](https://docs.trycurious.ai/concepts/variables.md): Placeholders in content: variables are filled from the user with a required fallback; parameters are facts you fix that every variant reproduces. - [Format and requirements](https://docs.trycurious.ai/concepts/format.md): The structural contract arm content must satisfy (types, lengths, enums, arrays) and the phrase rules every arm follows; both fixed for an experiment's life. - [Approval](https://docs.trycurious.ai/concepts/approval.md): Whether generated variants serve at once or wait for a person: options.approval, its manual default, what pending means, and how rejections teach. - [The experiment lifecycle](https://docs.trycurious.ai/concepts/lifecycle.md): From the first decide to a concluded variant: the three values of experiment_status, how variants are concluded, and what ends an experiment. - [Every decision returns the control](https://docs.trycurious.ai/troubleshooting/control-always-served.md): Why decide keeps serving the control: initializing, variants awaiting approval, every variant concluded, the holdout, sticky assignment, or a restart. - [Rewards are not being attributed](https://docs.trycurious.ai/troubleshooting/rewards-not-attributed.md): Events arrive but no rewards show: a name or properties mismatch, a different user id, an event outside the window, a wrong timestamp, or another environment. - [The SDK keeps serving the fallback](https://docs.trycurious.ai/troubleshooting/fallback-served.md): result.served is fallback: read error.code to tell a timeout from a wrong key, an undeclared element, a shape mismatch or an outage, and what fixes each. - [The API returns 409 conflict](https://docs.trycurious.ai/troubleshooting/conflict-409.md): What a 409 means: no live experiment for a publishable key, a conflicting identity link, the 50-arm limit, a lock_timeout, or a reused idempotency key. - [A request is rejected for an unknown field](https://docs.trycurious.ai/troubleshooting/unknown-field.md): A 400 with Unknown field(s) or Received unknown parameter: a misspelled field, the wrong case or bucket, or another endpoint's field; how to read the path. - [A user's history did not merge after identify](https://docs.trycurious.ai/troubleshooting/identify-not-merged.md): Anonymous and account ids are still separate: the call was refused, the ids are swapped, the decision raced the link, or the environments differ. - [The experiment restarted](https://docs.trycurious.ai/troubleshooting/experiment-restarted.md): A new experiment appeared and the status went back to initializing: a declaration-class field changed, often because two call sites disagree. - [API introduction](https://docs.trycurious.ai/api-reference/overview.md): The Curious API: base URL, authentication, environments, request and response conventions, the X-Request-Id header, and how the contract is versioned. - [Errors](https://docs.trycurious.ai/api-reference/errors.md): The error envelope, every HTTP status and stable error code with what to do about it, batch item errors, ambiguous failures, and the X-Request-Id header. - [Idempotency](https://docs.trycurious.ai/api-reference/idempotency.md): Making retries safe: the event id, decide's idempotency_key, exactly what a replay returns, recommended key formats, and a retry matrix by status. - [Rate limits](https://docs.trycurious.ai/api-reference/rate-limits.md): The per-organization request limit, the 429 response and its Retry-After header, what counts as a request, and how to stay under the limit by batching. - [Decide](https://docs.trycurious.ai/api-reference/decide.md): Serve content for a user and record the decision. - [Declare](https://docs.trycurious.ai/api-reference/declare.md): Configure an element without serving a user. - [Events](https://docs.trycurious.ai/api-reference/events.md): Report outcomes, singly or in batches of up to 200. - [Identify](https://docs.trycurious.ai/api-reference/identify.md): Link an anonymous user to a known user, or update a known user's state. ## OpenAPI Specs - [curious.openapi](/openapi/curious.openapi.yaml) This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.