# Double Opt-In Requests (/docs/preference-management/double-opt-in)

## What is Double Opt-In? [#what-is-double-opt-in]

Double opt-in is a two-step verification process that requires users to confirm their consent choices before they take effect. This approach:

- Provides stronger proof of consent by requiring users to verify their identity
- Ensures that the email address provided is valid and accessible by the user
- Creates an additional audit trail record for compliance purposes
- Helps meet regulatory requirements in regions like the EU

When you implement double opt-in with Transcend, the process works like this:

1. A user initiates a preference change (such as subscribing to marketing communications)
2. Instead of immediately applying the change, Transcend sends a verification email
3. The user clicks the confirmation link in the email
4. They are brought to a confirmation page in your Privacy Center
5. Once confirmed, the preference is updated in the Preference Store and any connected systems

This guide will walk you through implementing double opt-in for preference changes using the Transcend API.

## Setup Requirements [#setup-requirements]

Before implementing double opt-in, you'll need to gather these key values:

### 1. Determine Your Partition Value [#1-determine-your-partition-value]

The `partition` is the ID of the specific consent database you want to update. Most implementations use a single partition, but you might have multiple if you manage preferences separately for different brands or environments.

To find your partition value:

1. Go to [Preferences -> Developer Settings](https://app.transcend.io/preference-store/settings)
2. Ensure the Preference Store toggle is enabled
3. Click the **Open Partition Settings** button
4. Locate your desired partition and click the copy button
   - The default partition is labeled `BUNDLE_ID` - this is usually the one you'll want to use

![Preference Management Settings](/images/screenshot/2024-11-11-preference-management-settings.png)

![Preference Management Copy Partition Key](/images/screenshot/2024-11-11-partition-copy.png)

### Create API Key [#create-api-key]

To create an API key, you will want to go to [Developer Tools -> API Keys](https://app.transcend.io/infrastructure/api-keys) and create a new API key with the scope `Modify User Stored Preferences`.

Once created, you will only have one opportunity to save this API key. Please store the API key securely.

![Preference Management create API key](/images/screenshot/2024-11-11-preferece-api-key.png)

### Create a Double Opt-In Custom Field [#create-a-double-opt-in-custom-field]

In order to perform a double opt-in, you will need to tag your consent changes with this custom field.

To begin:

- Go to [Workspace Configuration -> Custom Fields](https://app.transcend.io/infrastructure/attributes)
- Ensure that there is a custom field called `Double Opt-In`.
- If no field exists with that name, create a new custom field of type `Single Select` that is enabled for the `DSR Automation Inbox -> Requests` table.

![Preference Management create double opt-in custom field](/images/screenshot/2024-11-11-double-opt-in-custom-field.png)

You may also add other tags for your consent change events that would be valuable for reporting and filtering. For example, you may want to create a custom field for the `Source` of a consent change event.

![Preference Management create source custom field](/images/screenshot/2024-11-11-source-custom-field.png)

### Determine your Sombra Endpoint [#determine-your-sombra-endpoint]

To determine which API endpoint you should use:

- Go to [Sombra](https://app.transcend.io/infrastructure/sombra/sombras) in your Transcend account
- Choose the <GlossaryTerm id="sombra">Sombra</GlossaryTerm> gateway that makes sense for your use case (you most likely will want to use the Sombra marked as "Is Primary Sombra?")
- Copy the "Transcend Ingress URL" value as your Sombra base URL

![Preference Management Sombra Gateway](/images/screenshot/2024-11-11-copy-sombra-ingress.png)

If you are self-hosting Sombra:

- Please ensure you are using a Sombra version >= `v7.253.0`.
- Add the `INTERNAL_KEY` bearer token in the `x-sombra-authorization` header. If you are using the bash commands below, you can do this by adding an additional header:

```shellscript
-H "x-sombra-authorization: Bearer $SOMBRA_API_KEY" \
```

### Find your Purpose and Preference Slugs [#find-your-purpose-and-preference-slugs]

When submitting requests to the Transcend API, you will want to update your purposes and preferences using their respective "Slug" values.

To find your purpose slugs, look at the "Slug" column under [Consent -> Regional Experiences -> Purposes](https://app.transcend.io/consent-manager/regional-experiences/purposes). To find your preference slugs, look at the "Slug" column under [Preferences -> Preference Topics](https://app.transcend.io/preference-store/preference-topics). To find your preference option slugs, look at the "Slug" column under [Preferences -> Preference Topics -> Options](https://app.transcend.io/preference-store/preference-options).

## Default Behavior (no double opt-in) [#default-behavior-no-double-opt-in]

### API Calls [#api-calls]

<APIOperation path="/v1/preferences" method="put" />

A single opt-in request can be submitted to Transcend via the `PUT /v1/preferences` API endpoint.

```shellscript
SOMBRA_BASE_URL="https://multi-tenant.sombra.transcend.io"
# SOMBRA_BASE_URL="https://multi-tenant.sombra.us.transcend.io"
PARTITION="776230e4-0fc7-4f62-9f35-44b71efdf8c3"
TRANSCEND_API_KEY="YOUR_API_KEY"
curl -X PUT "$SOMBRA_BASE_URL/v1/preferences" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $TRANSCEND_API_KEY" \
-d '{
  "records": [
    {
      "userId": "no-track@example.com",
      "partition": "'"$PARTITION"'",
      "timestamp": "2023-05-11T19:32:31.707Z",
      "purposes": [
        {
          "purpose": "Marketing",
          "enabled": true
        }
      ]
    }
  ]
}'
```

These requests will return a successful response that shows all purposes and preference updates have been applied immediately.

It will look like:

```json
{
  "success": true,
  "nodes": [
    {
      "userId": "no-track@example.com",
      "decryptionStatus": "DECRYPTED",
      "purposes": [
        { "purpose": "Marketing", "enabled": true, "preferences": [] }
      ],
      "partition": "776230e4-0fc7-4f62-9f35-44b71efdf8c3",
      "timestamp": "2024-11-12T02:03:53.175Z",
      "usp": null,
      "gpp": null,
      "tcf": null,
      "airgapVersion": null
    }
  ]
}
```

### Verifying changes in Admin Dashboard [#verifying-changes-in-admin-dashboard]

After making the API calls above, you will then be able to navigate to [Preferences -> User Preferences](https://app.transcend.io/preference-store/user-preferences) to see the resulting preference updated immediately in the Preference Store.

![Preferences updated after standard preference update](/images/screenshot/2024-11-11-preference-test-update.png)

If you have configured a consent workflow to run on consent change, you will see that new request under [DSR Automation -> Incoming Requests](https://app.transcend.io/privacy-requests/incoming-requests).

![Preference Management creates DSR automation record under incoming requests](/images/screenshot/2024-11-11-incoming-preference-change.png)

![Preference Management creates DSR automation record under incoming requests](/images/screenshot/2024-11-11-incoming-preference-change-purpose.png)

Because double opt-in has not been enabled for this request, the request made under "DSR Automation" will continue processing without sending an email confirmation to the user. You can optionally still choose to send an email receipt to the user confirming that their request is being processed.

## Double opt-in [#double-opt-in]

### API Calls [#api-calls-1]

<APIOperation path="/v1/preferences" method="put" />

A double opt-in request can be submitted to Transcend via the `PUT /v1/preferences` API endpoint.

```shellscript
SOMBRA_BASE_URL="https://multi-tenant.sombra.transcend.io"
# SOMBRA_BASE_URL="https://multi-tenant.sombra.us.transcend.io"
PARTITION="776230e4-0fc7-4f62-9f35-44b71efdf8c3"
TRANSCEND_API_KEY="YOUR_API_KEY"
curl -k -X PUT "$SOMBRA_BASE_URL/v1/preferences" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $TRANSCEND_API_KEY" \
-d '{
  "records": [
    {
      "userId": "no-track@example.com",
      "partition": "'"$PARTITION"'",
      "locale": "fr-FR",
      "timestamp": "2023-05-11T19:32:31.707Z",
      "purposes": [
        {
          "purpose": "Marketing",
          "enabled": true,
          "attributes": [{
             "key": "Double Opt-In",
             "values": ["true"]
          }, {
            "key": "Source",
            "values": ["Android App"]
          }]
        },
        {
          "purpose": "Analytics",
          "enabled": true
        }
      ]
    }
  ]
}'
```

These requests will return a successful response that shows all purpose and preference values have been accepted except for any purposes that require a double opt-in.

Note that `Analytics` has been updated immediately, while `Marketing` is set to its previous value, which was `enabled: false`.

```json
{
  "success": true,
  "nodes": [
    {
      "userId": "no-track@example.com",
      "timestamp": "2024-11-12T03:16:36.118Z",
      "partition": "776230e4-0fc7-4f62-9f35-44b71efdf8c3",
      "purposes": [
        { "purpose": "Analytics", "enabled": true, "preferences": [] },
        { "purpose": "Marketing", "enabled": false, "preferences": [] }
      ],
      "system": { "decryptionStatus": "DECRYPTED" },
      "consentManagement": {
        "usp": null,
        "gpp": null,
        "tcf": null,
        "airgapVersion": null
      }
    }
  ]
}
```

If this user had not previously opted in or out of the `Marketing` purpose, the response would show no entry for the `Marketing` purpose.

```json
{
  "success": true,
  "nodes": [
    {
      "userId": "no-track@example.com",
      "timestamp": "2024-11-12T03:16:36.118Z",
      "partition": "776230e4-0fc7-4f62-9f35-44b71efdf8c3",
      "purposes": [
        { "purpose": "Analytics", "enabled": true, "preferences": [] }
      ],
      "system": { "decryptionStatus": "DECRYPTED" },
      "consentManagement": {
        "usp": null,
        "gpp": null,
        "tcf": null,
        "airgapVersion": null
      }
    }
  ]
}
```

#### Setting locales [#setting-locales]

Note that in the above requests, the `locale` key can be provided to specify which translation of the email template should be used when sending the user a double opt-in.

Before calling the API with a specific locale, you must first update the set of allowed locales under the [Privacy Center -> General Settings](https://app.transcend.io/privacy-center/general-settings) tab on the Admin Dashboard.

![Privacy Center Language Setup](/images/screenshot/2024-11-13-privacy-center-locales.png)

Note that all content on the Privacy Center and emails can be customized and translated from [Privacy Center -> Content](https://app.transcend.io/privacy-center/messages-internationalization?globalMessageFilter=%7B%22locale%22%3A%22en%22%7D) section of the Admin Dashboard.

![Privacy Center Translation Setup](/images/screenshot/2024-11-13-translations-admin-dash.png)

### Verifying changes in Admin Dashboard [#verifying-changes-in-admin-dashboard-1]

After making the API calls above, you will then be able to navigate to [Preferences -> User Preferences](https://app.transcend.io/preference-store/user-preferences) to see the user inserted into the Preference Store. However you will notice that the purpose flagged for double opt-in has not yet changed in the Preference Store.

![Preferences updated after double opt in update has no marketing](/images/screenshot/2024-11-13-preference-store-double-opt-in.png)

If you have configured a consent workflow to run on consent change, you will see that new request under [DSR Automation -> Incoming Requests](https://app.transcend.io/privacy-requests/incoming-requests) with the "Double Opt-In" tag.

![Preference Management creates DSR automation record under incoming requests](/images/screenshot/2024-11-13-preference-store-double-opt-in-dsr-change.png)

Because the request has been flagged as a double opt-in, the request made under "DSR Automation" will send a confirmation email to the user and sit in a _Preflight_ state until the user clicks the link in their email to confirm the request change.

The request will look like the following on the Admin Dashboard:

![Preference Management DSR pending confirmation of double opt-in](/images/screenshot/2024-11-13-double-opt-in-request-preflight.png)

#### Confirming double opt-in [#confirming-double-opt-in]

The requestor will get a link in their inbox where they will be prompted to confirm their request.

![Preference Management double opt-in email confirmation](/images/2024-11-13-double-opt-in-request-email.png)

Clicking this link will bring them back to your Transcend Privacy Center where they will be presented with a confirmation screen:

![Privacy Center double opt-in email confirmation](/images/screenshot/2024-11-13-double-opt-in-request-email-confirmation.png)

After confirmation, the request will enter the _Compiling_ phase and queue up any updates in downstream systems.

![Preference Management DSR compiling after double opt-in confirmation](/images/screenshot/2024-11-13-double-opt-in-request-email-success-continue.png)

Additionally, the Preference Store will be updated to reflect the purpose and preference values that were consented to.

![Preference Management update after double opt-in confirmation](/images/screenshot/2024-11-13-double-opt-in-completed.png)

#### Rejecting double opt-in [#rejecting-double-opt-in]

If the requestor changed their mind or did not want to confirm their changes, they can reject the request by clicking the "Not you? Let us know." link in the email.

![Preference Management double opt-in email rejection](/images/2024_11_13_double_opt_in_request_email_reject.png)

Clicking this link will bring them back to your Transcend Privacy Center where they will be presented with a confirmation screen:

![Privacy center double-opt in rejection](/images/screenshot/2024-11-13-double-opt-in-request-email-rejection.png)

The request will enter the _Verification Failed_ phase and queue up any updates in downstream systems.

![Preference Management DSR failed verification after double opt-in confirmation](/images/screenshot/2024-11-13-double-opt-in-verification-failed.png)
