Query the Record of Consent (ROC) timeline for a single user. Every consent update that Transcend archives for that user is returned as one record, oldest first, so you can reconstruct what the user consented to at any point in time.
Each record reports the cumulative purpose and preference state at that timepoint, plus a diff against the previous record. Pass includeRawRequest to also receive the original archived payload for each record.
Rate Limits
- 100 requests per organization per minute (default).
- This limit can be increased upon request.
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.
Timeline ordering and diffs
- Records are returned most recent first, in chronological order.
preferencesAtCurrentTimeis the full cumulative state of every purpose the user has ever set at the time that record was received.changeFromPrevStatesplits the change introduced by the record intoadded,removedandupdatedpurposes. It is absent on the first record in the timeline, because there is no earlier record to compare against.- Diffs are computed at the purpose and preference level only. IAB strings (
tcf,gpp,usp) are not diffed — setincludeRawRequesttotrueand compare consecutive raw payloads if you need to audit those.
Limits
- This endpoint is not cursor-paginated. Omit
limitto receive the entire timeline in one response. limitmust be between 1 and 200. When provided, the most recentlimitrecords are returned.containsInitialRecordis always computed against the full timeline, even whenlimittruncates the returned records. It tells you whether the archive still holds the very first consent record for this user, which is what determines whether the timeline contains the true starting point or a partial view.
Identifiers
- Provide a single plaintext
identifier. The gateway validates, normalizes and encrypts it before the lookup, so plaintext identifiers never reach Transcend storage. identifier.namedefaults to the primary identifier configured for the partition, which isemailunless you have configured otherwise.- The lookup expands to every identifier linked to the same user, so querying by phone number returns the same timeline as querying by that user’s email.
- Identifiers inside
rawRequestare decrypted by your Sombra before being returned on this endpoint.
Raw archived records
rawRequestis present only whenincludeRawRequestistrue.- Unlike
preferencesAtCurrentTime, a raw record reflects exactly what was submitted:consentmay benullto indicate the purpose was cleared, andchoicemay benullto indicate a preference was cleared.
Empty results
- A user with no archived consent history returns
{ "records": [], "containsInitialRecord": false }rather than a 404.
POST
/v1/preferences/{partition}/consent-recordsIn your request headers, pass authorization: Bearer <<token>>.
If you're self-hosting Sombra, also add the request header x-sombra-authorization: Bearer <<sombraInternalKey>>. You can read more about request authorization here.
Requires scope:
View Managed Consent Database Admin API
authorizationstringAn API key generated from the Transcend dashboard: https://app.transcend.io/infrastructure/api-keys. |
x-sombra-authorizationstringThe Sombra internal key. This header is only needed for self-hosted Sombra gateways. See https://docs.transcend.io/docs/dsr-automation/api-integration/authentication#authenticating-to-sombra |
content-typestringSpecify content-type: application/json for a JSON response from the Transcend API. |
application/json
identifierobject(required)The user whose Record of Consent timeline should be returned. |
limitnumbermin:1max:200Maximum number of records to return, counting from the most recent. Omit to return the full timeline. |
includeRawRequestbooleandefault:falseWhether to include the raw archived payload for each record in the `rawRequest` field. |
Request Body Examples
Query a user's full consent timeline:
{
"identifier": {
"name": "email",
"value": "no-track@example.com"
}
}Query by a non-default identifier:
{
"identifier": {
"name": "phone",
"value": "+11234567890"
}
}Query using the default identifier name for the partition:
{
"identifier": {
"value": "no-track@example.com"
}
}Return only the ten most recent records:
{
"identifier": {
"name": "email",
"value": "no-track@example.com"
},
"limit": 10
}Include the raw archived payloads:
{
"identifier": {
"name": "email",
"value": "no-track@example.com"
},
"includeRawRequest": true
}200 (OK)
application/jsonReturns the user's Record of Consent timeline
Response Body
recordsarray<object>(required)The Record of Consent timeline for the user, ordered oldest first. Empty when no consent history is archived for this user. |
containsInitialRecordboolean(required)Whether the archive still holds the very first consent record for this user. When `false`, the timeline begins partway through the history and `records[0]` is not a true starting point. Always computed against the full timeline, even when `limit` truncates the response. |
Response Body Examples
Response for a user with two consent records:
{
"records": [
{
"preferencesAtCurrentTime": [
{
"purpose": "Marketing",
"consent": true,
"timestamp": "2024-10-07T20:44:35.000Z",
"preferences": []
}
]
},
{
"preferencesAtCurrentTime": [
{
"purpose": "Marketing",
"consent": true,
"timestamp": "2024-10-07T20:44:35.000Z",
"preferences": [
{
"topic": "Frequency",
"choice": {
"selectValue": "Weekly"
}
}
]
},
{
"purpose": "Analytics",
"consent": true,
"timestamp": "2024-10-08T20:44:35.000Z",
"preferences": []
}
],
"changeFromPrevState": {
"added": [
{
"purpose": "Analytics",
"consent": true,
"timestamp": "2024-10-08T20:44:35.000Z",
"preferences": []
}
],
"removed": [],
"updated": [
{
"purpose": "Marketing",
"consent": true,
"timestamp": "2024-10-07T20:44:35.000Z",
"preferences": [
{
"topic": "Frequency",
"choice": {
"selectValue": "Weekly"
}
}
]
}
]
}
}
],
"containsInitialRecord": true
}Response including the raw archived payloads:
{
"records": [
{
"preferencesAtCurrentTime": [
{
"purpose": "Marketing",
"consent": true,
"timestamp": "2024-10-07T20:44:35.000Z",
"preferences": []
}
],
"rawRequest": {
"timestamp": "2024-10-07T20:44:35.000Z",
"confirmed": true,
"partition": "ee1a0845-694e-4820-9d51-50c7d0a23467",
"metadata": null,
"identifiers": [
{
"name": "email",
"value": "no-track@example.com"
}
],
"purposes": [
{
"purpose": "Marketing",
"consent": true,
"timestamp": "2024-10-07T20:44:35.000Z",
"preferences": []
}
]
}
},
{
"preferencesAtCurrentTime": [],
"changeFromPrevState": {
"added": [],
"removed": [
{
"purpose": "Marketing",
"consent": true,
"timestamp": "2024-10-07T20:44:35.000Z",
"preferences": []
}
],
"updated": []
},
"rawRequest": {
"timestamp": "2024-11-02T09:12:04.000Z",
"confirmed": true,
"partition": "ee1a0845-694e-4820-9d51-50c7d0a23467",
"metadata": "{\"version\":\"1.0.0\"}",
"identifiers": [
{
"name": "email",
"value": "no-track@example.com"
}
],
"purposes": [
{
"purpose": "Marketing",
"consent": null,
"timestamp": "2024-11-02T09:12:04.000Z"
}
]
}
}
],
"containsInitialRecord": true
}Response for a truncated timeline:
{
"records": [
{
"preferencesAtCurrentTime": [
{
"purpose": "Marketing",
"consent": true,
"timestamp": "2024-10-07T20:44:35.000Z",
"preferences": []
}
]
}
],
"containsInitialRecord": true
}Response for a user with no Record of Consent history:
{
"records": [],
"containsInitialRecord": false
}400 (Bad Request)
application/jsonBad Request
Response Body
errorsarray<string>Examples:
|
401 (Unauthorized)
application/jsonThere was a problem authenticating your request. This may be an issue with the Transcend API key ("authorization" header), or the Sombra API key ("x-sombra-authorization" header used for self-hosted gateways only).
413 (Request Entity Too Large)
application/jsonThe request body is too large. JSON and raw bodies must be less than 50MB. URL encoded bodies must be less than 30MB.
429 (Too Many Requests)
application/jsonYou are sending requests too quickly and have hit our rate limit. If you hit this, you'll need to throttle your request velocity or try again later.
Response Headers
Retry-Afterinteger |
X-RateLimit-Limitinteger |
X-RateLimit-Remaininginteger |
X-RateLimit-Resetinteger |
500 (Internal Server Error)
application/jsonA 5xx error means there is either an issue with your self-hosted gateway, or a Transcend server is having issues. You check our system status at status.transcend.io. Please reach out to Transcend support if you're experiencing this error.
502 (Bad Gateway)
application/jsonAn upstream service on Transcend's side is having issues. You check our system status at status.transcend.io. Please reach out to Transcend support if you're experiencing this error.