Releases
Consents API update
Updated: 30 September 2026
In order to improve the experience and performance of the Didomi Consents API, we are updating the logic by which end-users are identified in the API and how their consent records can be merged/calculated into a comprehensive consent profile.
Overview of changes
Once the new API behavior is activated for your organization, the Consents API will guarantee that one organization user ID (OUID) corresponds to exactly one end-user record. The end-user's full consent state will live on that single record.
Most clients use the OUID to refer to a concrete end-user in their own system. The Consents API historically did not enforce that one-to-one relationship (i.e. multiple end-user records could share the same OUID, with their consent state spread across those records). This update aligns the API with the way most clients already treat the OUID.
The update is a single design change with two complementary halves (both designed to avoid breaking existing requests) and will enable Didomi to enforce this one-to-one relationship. Each half affects a different part of your system.
Prevention (affects how requests are handled)
New end-users are written under the one-OUID-one-user rule from the moment the behavior is activated. The API contract is unchanged — no new error codes, no payload-shape changes, no removed fields.
When creating an event or a user, an OUID supplied in the request payload becomes authoritative. The service resolves the user via the OUID — reusing the existing user if one already exists under that OUID, or creating a new one if none does — and ignores any UID also supplied in the same payload.
New users created with an OUID receive the same value as their user ID to ensure unicity.
PATCH /consents/users/{id}no longer allows mutating the OUID.
Details per endpoint is available in Changes per endpoint.
Consolidation (affects existing data)
Existing multi-user OUIDs in your historic data are consolidated into a single canonical user record via a live migration. The migration runs on GET /users/{id}?$by_organization_user_id=true&$merge_users=true .
When the Consents API is asked for a user via an OUID that maps to multiple users on this endpoint, it computes the merged consent state and persists it as a new canonical user record under that OUID.
From that point onward, the new API behavior resolves every request targeting that OUID — reads and writes alike, including events — to the canonical record, instead of re-merging on each call.
The historic user records and their events are retained and remain fully reachable on demand. See: Retrieve historic source records.
Additional details available in Consolidation of existing multi-user OUIDs.
Benefits
This change is not just a contract cleanup — it is a measurable upgrade on two fronts your integration touches every day, ergonomics and latency:
A single end-user record per OUID
Previously, an OUID could be associated with multiple user_id records, scattering both consent state and event history across those records. Under the new behavior, each OUID resolves to a single canonical end-user record.
Reads return that consolidated state
Writes (including event creation) land on the same record instead of spawning siblings.
A single canonical record per OUID makes a broad range of API interactions noticeably more straightforward and convenient.
Lower read latency
Consolidated state is now precomputed and persisted which significantly improves latency of user read requests.
Rollout and opt-in
The 2026-01-01 behavior is being rolled out in phases. Your organization's path through the rollout depends on whether your organization is an existing or a new client. Click the tabs below for more information.
Existing Didomi clients will fall into one of two groups depending on how these organizations use the Consents API.
Not calling the API directly or using it only through Didomi SDKs
If your organization does not call the Consents API directly — or calls it only through Didomi's SDKs (web or mobile) — the new behavior is enabled for you automatically by Didomi. The changes are transparent at the SDK boundary and no integration work is required on your side.
Calling Consents API directly
Clients integrating directly against the Consents API have a grace period during which the previous behavior remains the default. The new behavior is gated entirely behind a request header. In order to activate the behavior on a given request, include the following in the header:
Requests without this header continue to behave exactly as they did before the update.
Use the provided grace period to audit your integration against the scenarios posed in the Impact assessment section below and to verify your downstream consumers against the new behavior.
After the grace period ends, Didomi will enable the new behavior automatically for these clients.
Organizations that begin integrating with the Consents API after the rollout will receive the 2026-01-01 behavior unconditionally. The header is not required, and there is no historic-behavior fallback for these clients — the API exposes the new contract immediately.
Impact Assessment
Didomi has collated the following questions in order to help your organization understand whether it is impacted by the new behavior.
Do you send both
user.id(UID) anduser.organization_user_id(OUID) on the same write request? The OUID is now authoritative; the UID is ignored. See the following: - Create a new event - Create a new user - Consent link eventsDo you call
PATCH /consents/users/{id}expecting to changeorganization_user_id? The API no longer allows patching the OUID. See: Patch a userDo you use Didomi's cross-device feature, or do you call read endpoints with
$merge_users=truetoday? This applies only to the subset of end-users whose OUID is shared across multipleuser_idrecords and are being read using$merge_users=true— for those, the merged consent state is now persisted as a canonical user record. End-users with a single record per OUID are not touched. Cross-device clients receive this behavior automatically. See: Consolidation of existing multi-user OUIDsDo any downstream consumers (data warehouse, BI joins, schema validators) assume
user.idis a UUID? Under the new behavior, new OUID-keyed users — including those produced by the migration — receive the OUID as theiruser.id. Since OUIDs are typically client-supplied hashes rather than generated UUIDs, theuser.idformat shifts away from UUID for those records. See the following: - Changes per endpoint - Consolidation of existing multi-user OUIDs
Changes per endpoint
The matrices below describe the new behavior under the 2026-01-01 profile. The thread running through all four endpoints is the same: when an OUID is provided, the OUID wins. Each endpoint section opens with one or two request examples that show the divergent behavior directly, before the matrix.
Create a new event
The endpoint enables your organization to create a new consent event for a new or existing end-user. In the body of the request, your organization identifies the end-user via user.id (UID) or user.organization_user_id (OUID).
OUID not provided (guest consent)
OUID provided & exists
OUID provided & does not exist
UID not provided
Return 400
User updated via OUID
User created with provided OUID. UID for the user duplicates the provided OUID.
UID provided & exists
User updated via UID
New behavior — Ignore provided UID and update end-user consent record via provided OUID
New behavior — Ignore provided UID (that end-user record is not updated). Create a new user with the provided OUID. UID for the new user duplicates the provided OUID.
UID provided & does not exist
User created with provided UID
New behavior — Ignore provided UID and update end-user consent record via provided OUID
New behavior — Ignore provided UID and create a new user with the provided OUID. UID for the new user duplicates the provided OUID.
Create a new user
The endpoint enables your organization to create a new user to store their consent record. In the body of the request, your organization identifies the new end-user via id (UID) or organization_user_id (OUID).
OUID not provided (guest consent)
OUID provided & exists
OUID provided & does not exist
UID not provided
User created with a generated id
New behavior — Returns 204. User not created.
User created with the provided OUID. UID for the user duplicates the provided OUID.
UID provided & exists
Returns 204. User not created.
Returns 204. User not created.
New behavior — Ignore UID. Create user with the provided OUID. UID for the user duplicates the provided OUID.
UID provided & does not exist
User created with the provided UID
New behavior — Returns 204. User not created.
New behavior — Ignore UID. Create user with the provided OUID. UID for the user duplicates the provided OUID.
Patch a user
The endpoint enables your organization to update an existing user's data and/or consent status. Your organization identifies the end-user via id (UID) or organization_user_id (OUID).
User has no OUID (null)
User has OUID
OUID not provided
User is patched, OUID is unchanged (null)
User is patched, OUID is unchanged
OUID provided as null
User is patched, OUID is unchanged (null)
New behavior — User is patched; OUID is not patched and retains its original value
OUID provided & not modified
User is patched, OUID is unchanged (null)
User is patched, OUID is unchanged
OUID provided & different
New behavior — User is patched; OUID is not patched and remains (null)
New behavior — User is patched; OUID is not patched and retains its original value
Consent link events
A consent link is a pre-authenticated URL that creates a consent event when accessed from a browser. End-users use these links to update their consent status. Didomi supports two types of authorization for consent links:
Pre-authorized — link created beforehand via the Didomi API; carries a unique signed token in the URL.
Digest — link created ad-hoc with a unique hash digest or HMAC signature; no API call required and can be generated on your server.
Consent link events follow the same matrix as Create a new event — when both UID and OUID are present, the OUID is authoritative. See the request examples in Create a new event — they apply equally to the event a consent link generates.
OUID not provided (guest consent)
OUID provided & exists
OUID provided & does not exist
UID not provided
Return 400
User updated via OUID
User created with provided OUID. UID for the user duplicates the provided OUID.
UID provided & exists
User updated via UID
New behavior — Ignore provided UID and update end-user consent record via provided OUID
New behavior — Ignore provided UID (that end-user record is not updated). Create a new user with the provided OUID. UID for the new user duplicates the provided OUID.
UID provided & does not exist
User created with provided UID
New behavior — Ignore provided UID and update end-user consent record via provided OUID
New behavior — Ignore provided UID and create a new user with the provided OUID. UID for the new user duplicates the provided OUID.
Consolidation of existing multi-user OUIDs
Multi-user OUIDs are consolidated by a live migration that runs on a single endpoint:
This is the canonical read path for OUID-keyed user lookups, and is also the endpoint Didomi's cross-device sync uses. Historically, when this endpoint encountered an OUID associated with multiple user records, it computed a consolidated consent state across those records in memory and returned the merged view in the response — this operation is referred to as user merging. The underlying records remained unmerged in storage; the next call recomputed the merge from scratch.
Under the 2026-01-01 behavior, the first call for a multi-user OUID still triggers the same in-memory merge — but the result is now persisted as a new canonical user record under that OUID, with user id set to the OUID value. From that point onward, every request targeting that OUID — reads on this endpoint, events written against the OUID, anything else — resolves to the new canonical record instead of re-merging.
Consolidated record overview
The consolidated record adopts the OUID as its user id, matching the identity rule applied to any new user created with an OUID under the new behavior. See Prevention (affects your request code).
The persisted record holds the same merged state that the original $merge_users=true call returned in its response body. All consent statuses across all regulations covered by the historic users of this OUID are carried over.
Event histories are preserved but stay on their original user records. Events that the historic users accumulated are not deleted, and they are not moved either: they remain attached to their original user.id in the database and can be queried through the patterns described in Retrieving historic source records. The canonical record starts with its own event history, which begins accumulating from the first event submitted against the OUID after consolidation.
A consolidated record is tagged so downstream systems can recognize it as a consolidation product. A user record produced by the migration carries a non-empty api_metadata object:
User records that were not produced by consolidation carry an empty api_metadata object ({}), so a simple presence check on api_metadata.merge_fix_user is sufficient to distinguish the two.
Enable user merging and consolidation
Historically, clients managed user merging via the $merge_users query parameter. The parameter is still honored for clients who already rely on it. It is disabled by default for clients who have not used it and for new clients.
Consolidation of merged users can be activated either by sending the 2026-01-01 opt-in header on the request, or by an organization-level feature flag managed by Didomi. Either mechanism is sufficient; both can be used in combination during a staged rollout.
Merging disabled
No merging takes place.
$merge_users=true enabled and consolidation of merged users not activated (no 2026-01-01 header and no organization-level flag)
Merged state is computed in memory per request and not persisted.
$merge_users=true enabled and consolidation of merged users activated (either the 2026-01-01 header or the organization-level flag)
Merged state is computed once, persisted as a canonical record, and returned on subsequent reads.
Retrieve historic source records
The historic user records involved in the merge are not deleted. They are hidden from default reads but remain fully reachable on demand. The Consents API offers three patterns for working with historic records:
Downstream - webhooks and batch exports
There is no change to the shape of webhook events or batch exports. However, the data flowing through them reflects the new contract:
New canonical user records. Consolidated user records produced by the migration are emitted as new user records with
id == organization_user_idand theapi_metadata.merge_fix_user: trueflag set.OUID-keyed new users emit matching user
id. For new users created with an OUID under the new contract,idis the OUID value. Downstream joins keyed on either field continue to work.Fewer user-creation events. Requests that previously spawned a new user record for an already-known OUID now reuse the existing OUID-keyed user. Webhooks and batch exports may see a meaningfully lower volume of user-creation events as a result, especially for clients that historically produced many user records per OUID.
Historic UIDs stop receiving new events. Once a canonical record is in place under an OUID, all subsequent events route to it. The pre-consolidation UIDs are still queryable via
$deduplicate_users=falsebut will not appear in new event streams.
Last updated