POST /identify declares that two ids are the same person, or updates a known user’s identifiers and attributes without a decision. Secret keys only: the browser never holds the authority to merge identities. Full field reference: the endpoint.
Linking
anonymous_id is the id you decided and reported events with before the person was known; user_id is who they turned out to be. After the call, decisions and events on either id attribute to the merged user, so a reward reported under user_id credits a decision made under anonymous_id. The link is durable: many anonymous ids may link into one known user, and a retry of the same link is a harmless no-op.
A declaration that conflicts with existing links, for example an anonymous id already linked to a different known user, is a 409 with { "error": "conflict", "message": "Identity conflicts with an existing user" }. Resolve it on your side; Curious does not guess.
Profile-only updates
Omitanonymous_id to update a known user’s state:
decide: identifiers are durable identity (email, name, phone) and attributes are durable state (plan, company size). You pick the bucket; nothing is routed by key name. A different bucket name such as traits is a 400 with Received unknown parameter: traits. Explicit values win per key; unchanged state writes nothing.
Sequencing
Identify is an ordered mutation, not telemetry. Send it the moment the person becomes known, and await it before a decision that should see the merged profile. The server SDK sends it at once, retries only transient failures, and never queues it behind events.Login
- Before login, the client decides and reports events under an anonymous id (the browser SDK mints
anon_<uuid>in a first-party cookie; a mobile app can use an installation id). - On login or signup, your server calls
identifywithanonymous_idand the account’suser_id, and awaits the response. - The client switches to the account’s
user_idfor every laterdecideandeventscall.
Logout
Stop sending the account’suser_id, and start a fresh anonymous id. Never reuse the anonymous id from before login: it is now linked to the account, so the next person on the same device would be attributed to it. The browser SDK’s reset() does exactly this.
Several accounts, one device
Each login links that session’s anonymous id to that account. Linking the same anonymous id to a second account is the409 above, which is why logout must mint a new anonymous id before anyone else signs in.
With the server SDK
identify() throws a CuriousError with code identity_conflict on a 409. See Events and identify with the server SDK.
If decisions and events under the two ids are still separate after a link, see A user’s history did not merge after identify.