# Consent Purpose Provenance (/docs/preference-management/consent-purpose-provenance)

## Overview [#overview]

Preference Management records **provenance** on each purpose in a preference record: the Transcend channel that wrote the last consent change, and the upstream system your integration named. The Admin Dashboard shows both on the purpose card, and both are available for audit and reporting. When a consent change triggers a Preference Workflow, Transcend also stamps why that purpose's consent flipped on the resulting data subject request (DSR).

Related: [Storing Consent Preferences](./storing-consent-preferences.mdx) and [PUT /v1/preferences](/docs/api-reference/preferences-server-side/put-v1-preferences).

## View provenance in the Admin Dashboard [#view-provenance-in-the-admin-dashboard]

1. Open **Preference Management** and find the preference record.
2. Open the record detail. Each purpose appears as a card with a consent control.
3. Read the card footer. It shows three values, separated by dots.

![Example of a Admin Dashboard update purpose](/images/sanity/cleanshot-2026-08-27-at-10.54.06-2x.png)

![Example of a Privacy Center updated purpose](/images/sanity/privacy-center-provenance.png)

| Footer label          | What it means                                                                                                                                                                      |
| --------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Consent last provided | When that purpose last changed.                                                                                                                                                    |
| Source system         | The upstream system your integration named, for example Adobe. Only an API caller can set it, so it shows **None** for Admin Dashboard, Privacy Center, and Consent Manager edits. |
| Last updated via      | The Transcend channel that wrote the update: Admin Dashboard, Privacy Center, Consent Manager, or API. Transcend sets this from the write path, so you cannot choose it.           |

## Set the source system through the API [#set-the-source-system-through-the-api]

On [PUT /v1/preferences](/docs/api-reference/preferences-server-side/put-v1-preferences), include an optional `sourceSystem` on each purpose you update to name the upstream system that drove the change. Leave it out when there is no upstream system to name. These writes show **Last updated via** as **API**.

Example purpose fragment:

```json
{
  "purpose": "EnterpriseMarketing",
  "enabled": true,
  "timestamp": "2026-08-24T18:00:00.000Z",
  "sourceSystem": "Adobe"
}
```

Use an API key with the **Modify User Stored Preferences** scope. For self-hosted Sombra, also send `x-sombra-authorization` as described in the [API reference](/docs/api-reference/preferences-server-side/put-v1-preferences).

## Consent workflow provenance [#consent-workflow-provenance]

When Preference Management flips a purpose's consent value and a consent workflow creates a data subject request (DSR), Transcend stamps a request custom field:

<table>
  <tbody>
    <tr>
      <td>
        Custom field key
      </td>

      <td>
        Values
      </td>
    </tr>

    <tr>
      <td>
        `PurposeChangeProvenance`
      </td>

      <td>
        `manual` · `cascade` · `expiration`
      </td>
    </tr>
  </tbody>
</table>

Most organizations only see `manual`. The `cascade` and `expiration` values appear only if consent rules are enabled for your organization (for example linked-purpose cascade or purpose expiration). Contact Transcend if you are unsure whether those rules apply to you.

![DSR Request Details page showing custom fields > provenance value with "cascade" as the attribute.](/images/sanity/cleanshot-2026-08-18-at-11.29.30-2x.jpg)

### What each value means [#what-each-value-means]

<table>
  <tbody>
    <tr>
      <td>
        Value
      </td>

      <td>
        When it is stamped
      </td>
    </tr>

    <tr>
      <td>
        `manual`
      </td>

      <td>
        Default for all tenants. A consumer, admin, API, or Preference Center write changed the purpose consent value directly. Also used when no other cause is recorded.
      </td>
    </tr>

    <tr>
      <td>
        `cascade`
      </td>

      <td>
        Only if linked-purpose consent rules are enabled. Consent rules clamped the purpose because a parent was revoked (`requires` or `cascade` rule).
      </td>
    </tr>

    <tr>
      <td>
        `expiration`
      </td>

      <td>
        Only if purpose expiration is enabled. The expire sweep flipped consent after the purpose's `expiresAt` elapsed.
      </td>
    </tr>
  </tbody>
</table>

<Callout type="info" title="Provenance vs metadata updates">
  Provenance describes **why purpose consent flipped**, not metadata-only updates. Stamping `expiresAt` on a still-granted purpose does **not** produce an `expiration` tag. That value is reserved for the expire sweep that actually flips consent.
</Callout>

### Where to see it [#where-to-see-it]

1. Ensure a custom field named `PurposeChangeProvenance` exists under Infrastructure → Custom Fields (type Single Select, enabled on DSR Automation Inbox → Requests, with values `manual`, `cascade`, and `expiration`). See [Managing Custom Fields](../overview/platform/custom-fields.mdx).
2. After a consent change that triggers a Preference Workflow, open the resulting request under DSR Automation → Incoming Requests and read the `PurposeChangeProvenance` value. See [View the Status of a Request](../dsr-automation/processing-requests/view-status-of-a-request.mdx).

### Using provenance in integrations [#using-provenance-in-integrations]

Consent-workflow DSRs expose request custom fields to database integrations as templatable variables. The attribute key is camelCased, so `PurposeChangeProvenance` becomes `{{customField_purposeChangeProvenance}}`. See [Database Integration Set Up for DSR Automation](../integrations/custom/database-integration-set-up-for-dsr-automation.mdx).

Example pattern:

```sql
CASE {{customField_purposeChangeProvenance}}
  WHEN 'cascade' THEN /* parent-driven clamp - only if consent rules are enabled */
  WHEN 'expiration' THEN /* time-bounded consent ended - only if expiration is enabled */
  ELSE /* manual / default */
END
```

You do not pass `PurposeChangeProvenance` in the [PUT /v1/preferences](/docs/api-reference/preferences-server-side/put-v1-preferences) body. Preference Management stamps it when the workflow is created. Other workflow custom attributes you supply are preserved alongside it.
