Upsert user preferences
Batch-upsert preference records for multiple users.
Rate Limits
- 10000 preference records per organization per minute (default).
- This limit can be adjusted per organization upon request.
Note: Unlike other Preferences API endpoints, the upsert preferences endpoint has a default rate limit of 10,000 preference records per organization per minute, not 10,000 requests per minute. This means that you can update up to 10,000 preference records in batches of any size (up to 100 records per batch) within a minute. For example, you could update 100 records in a single request, or 10 records in each of 10 requests, and both would consume the same portion of your rate limit (100 records).
Rate Limiting Headers
X-RateLimit-Limit: The maximum number of requests allowed in the current window.X-RateLimit-Remaining: The number of requests remaining in the current window.X-RateLimit-Reset: The time at which the current rate limit window resets in ISO 8601 format.Retry-After: (on 429) The number of seconds to wait before making a new request.
Transcend ID (Record Lookup by Stable Identifier)
- Every preference record has a system-managed
transcendidentifier — a stable UUID automatically assigned by the system. - Use
{ "name": "transcend", "value": "<uuid>" }in theidentifiersarray to look up and update an existing record. - Transcend ID is returned in all successful responses alongside other identifiers.
- You cannot create a new record using only a
transcendidentifier — it must resolve to an existing record. - If the UUID does not match any existing record, the affected record is returned in
failureswith the error: "The transcend identifier in this request does not match any consent profile for this organization." - The
transcendidentifier is system-managed and immutable from client mutations.
Per-purpose timestamps
purposes[].timestampis optional and must be an ISO 8601 timestamp when provided. If omitted, the purpose falls back to the record-leveltimestamp.- The record-level
timestampstill reflects the most recent time any purpose on the record changed. - If a purpose value is unchanged, its stored per-purpose timestamp is preserved even when the request includes a newer record-level
timestamp. - Updating one purpose does not change another purpose's stored timestamp.
- Future timestamps are accepted to tolerate clock drift.
- If an incoming purpose timestamp is older than the stored timestamp for the same purpose, the write succeeds but the newer stored consent value and timestamp are kept.
- For large historical backfills, send sequential
PUTrequests ordered oldest-first instead of relying on one request to backdate multiple purposes with conflicting times.
Source system (audit tagging)
purposes[].sourceSystemis optional. When provided, it tags the purpose update with the external system that made the change (for example, a CRM or marketing automation platform).- Useful for automated consent updates where you want an audit trail of where each change originated.
- When omitted, no source system is recorded for that purpose update.
Transcend_API_Key Modify User Stored PreferencesAuthorizationBearer <token>authorization: Bearer <>
Scope: Modify User Stored Preferences
content-type*stringSpecify content-type: application/json for a JSON response from the Transcend API.
application-jsonapplication/json- body
records*array<>The list of user preferences records to update.
items <= 100skipWorkflowTriggers?booleanWhether to skip triggering workflows associated with the purpose change event.
falseReturns whether the operation was successful and the upserted records
application/json- response
success?booleanWhether the preferences were updated successfully
nodes?array<>User's preference records
curl -X PUT 'https://multi-tenant.sombra.transcend.io/v1/preferences' \ -H 'authorization: string' \ -H 'content-type: string' \ -H 'Content-Type: application/json' \ -d '{ "records": [ { "partition": "ea3a0845-694e-4820-9d51-50c7d0a23467", "timestamp": "2026-01-15T12:05:00.000Z", "identifiers": [ { "name": "email", "value": "no-track@example.com" } ], "purposes": [ { "purpose": "Marketing", "enabled": true, "timestamp": "2026-01-14T12:04:00.000Z" } ] } ]}'{ "success": true, "nodes": [ { "partition": "ee1a0845-694e-4820-9d51-50c7d0a23467", "timestamp": "2023-04-11T15:09:28.403Z", "identifiers": [ { "name": "transcend", "value": "a1b2c3d4-e5f6-7890-abcd-ef1234567890" }, { "name": "email", "value": "no-track@example.com" }, { "name": "phone", "value": "+11234567890" } ], "purposes": [ { "purpose": "Advertising", "enabled": true, "timestamp": "2026-01-15T12:05:00.000Z" }, { "purpose": "Analytics", "enabled": true, "timestamp": "2026-01-15T12:05:00.000Z" }, { "purpose": "ProductUpdates", "enabled": true, "timestamp": "2026-01-15T12:05:00.000Z", "preferences": [ { "topic": "Frequency", "choice": { "selectValue": "Weekly" } }, { "topic": "Channel", "choice": { "selectValues": [ "Email", "Sms" ] } }, { "topic": "Unsubscribe", "choice": { "booleanValue": true } } ] } ], "consentManagement": { "usp": null, "gpp": null, "tcf": null, "airgapVersion": null }, "system": { "updatedAt": "2023-06-13T08:02:21.793Z", "decryptionStatus": "DECRYPTED" }, "metadata": [ { "key": "version", "value": "1.0.0" } ], "metadataTimestamp": "2023-06-13T08:02:21.793Z" }, { "partition": "ee1a0845-694e-4820-9d51-50c7d0a23467", "timestamp": "2023-05-11T15:09:28.403Z", "identifiers": [ { "name": "transcend", "value": "c3d4e5f6-a7b8-9012-cdef-123456789012" }, { "name": "email", "value": "no-track-pls@transcend.io" }, { "name": "phone", "value": "+11334567891" } ], "purposes": [ { "purpose": "Advertising", "enabled": true, "timestamp": "2026-01-15T12:05:00.000Z" }, { "purpose": "Analytics", "enabled": true, "timestamp": "2026-01-15T12:05:00.000Z" }, { "purpose": "ProductUpdates", "enabled": false, "timestamp": "2026-01-15T12:05:00.000Z" } ], "consentManagement": { "gpp": null, "tcf": null, "airgapVersion": null, "usp": "1YYN" }, "system": { "updatedAt": "2023-06-13T08:02:21.793Z", "decryptionStatus": "DECRYPTED" }, "metadata": [ { "key": "version", "value": "1.0.0" } ], "metadataTimestamp": "2023-06-13T08:02:21.793Z" } ]}