--- title: "How to Update Natterbox Consent based on DNC fields" slug: "how-to-update-consent-based-on-dnc-fields" updated: 2026-07-02T19:29:35Z published: 2026-07-02T19:29:35Z canonical: "docs.natterbox.com/how-to-update-consent-based-on-dnc-fields" --- > ## Documentation Index > Fetch the complete documentation index at: https://docs.natterbox.com/llms.txt > Use this file to discover all available pages before exploring further. # How to Update Natterbox Consent based on DNC fields > [!NOTE] > This guide is intended for [advanced Salesforce admins](/v1/docs/advanced-salesforce-integration-examples). For Salesforce education, contact Salesforce directly or use trailheads for specific knowledge. This guide walks you through building a record-triggered Salesforce Flow that automatically updates a contact's Natterbox Consent records when the standard Do Not Call checkbox on the Contact changes. The flow handles both directions in a single automation: opting the customer out when Do Not Call is ticked, and opting them back in when it is unticked. This is useful when a customer requests opt-in or opt-out through a channel other than messaging, for example a web form, a phone call, or an email. ## Prerequisites - Natterbox Messaging is configured in your Salesforce org with the Natterbox managed package installed. - At least one Natterbox Consent record exists in your org. Consent records are created automatically when messaging conversations begin. - You have the **System Administrator** profile, or the **Manage Flows** permission. - You understand how the Natterbox consent model works, in particular that a consent record represents a unique phone-number pairing (your number and the customer's number), not a contact. See [Keywords & Consent](/v1/docs/keywords-consent). ## How consent records work Before building the flow, it is important to understand the fields the flow will set. A Natterbox Consent record (`nbavs__Consent__c`) is considered **active** based on a combination of three fields: `nbavs__Status__c`, `nbavs__Temporary__c`, and `nbavs__ConsentEndTime__c`. Only certain combinations of these values are valid. | Status | Temporary | Consent End Time | Meaning | | --- | --- | --- | --- | | `Opt In` | Unchecked (false) | Empty | Permanent consent. The record is active indefinitely. | | `Opt In` | Checked (true) | Set (in the future) | Temporary consent (for example, implied consent when a customer messages in first). The record is active only until the end time. | | `Opt Out` | Unchecked (false) | Set (now) | Opted out. The record is not active. | > [!WARNING] > Always set the Consent End Time when opting out > > Setting `Status = Opt Out` with `Temporary = false` but leaving the **Consent End Time** empty produces an invalid state that can break consent processing on a live org. Whenever this flow opts a contact out, it must also set the Consent End Time to the current date and time. Likewise, when opting a contact back in permanently, the flow must clear the Consent End Time. The flow therefore sets the fields as follows: - **Do Not Call = true (opt out):** Status = `Opt Out`, Temporary = `false`, Consent End Time = the current date and time. - **Do Not Call = false (opt in):** Status = `Opt In`, Temporary = `false`, Consent End Time = cleared (empty), giving permanent consent. ## Matching consent records to a contact The Natterbox Consent object does **not** have a lookup to the Contact. Instead, each record stores the customer's number in `nbavs__ExternalAddress__c` and your number in `nbavs__InternalAddress__c`. To find a contact's consent records, the flow matches `nbavs__ExternalAddress__c` against the contact's phone number. A single customer number can be paired with several different Natterbox-owned numbers (for example a sales line and a support line), and each pairing is a separate consent record. To catch every one of them, the flow first retrieves all consent records whose External Address matches the contact's number, then loops through the returned collection so that each record is evaluated and updated individually. > [!WARNING] > Phone number format matters > > The External Address is stored as full international digits with no plus sign, spaces, or punctuation, for example `447450295814` (UK) or `12483454273` (US). A standard Contact phone field such as `MobilePhone` is usually stored with formatting (for example `+44 7450 295814` or `(248) 345-4273`), so a direct comparison will not match. Before comparing, strip the formatting from the contact's number, and make sure it resolves to the same international format (including country code) as the stored External Address. The most reliable approach is to hold a normalised, digits-only version of the number on the Contact. ## Building the flow ### Step 1: Create a new record-triggered flow 1. Click the **Setup** cog in Salesforce and select **Setup**. 2. In the Quick Find box, search for **Flows** and click **Flows**. 3. Click **New Flow**. 4. Select **Start From Scratch** and then **Next**. 5. Select type **Record-Triggered Flow** and then **Create**. ### Step 2: Configure the trigger (Start element) Click the **Start** element and configure the following: - Object: `Contact` - Trigger the Flow When: **A record is updated** - Condition Requirements: **Formula Evaluates to True** - Formula: ```plaintext ISCHANGED({!$Record.DoNotCall}) ``` - Optimize the Flow for: **Actions and Related Records** This ensures the flow only runs when the Do Not Call field actually changes value, rather than on every Contact update. ### Step 3: Create a phone-matching formula Create a formula resource that strips formatting from the contact's number so it can be compared against the stored External Address. 1. In the **Toolbox**, next to **Manager**, click **New Resource**. 2. Resource Type: **Formula**. 3. API Name: `forExternalAddress`. 4. Data Type: **Text**. 5. Formula (adjust to match the phone field you use, and to prefix a country code if required by your data): ```plaintext SUBSTITUTE(  SUBSTITUTE(    SUBSTITUTE(      SUBSTITUTE(        SUBSTITUTE({!$Record.MobilePhone}, "+", ""),      " ", ""),    "-", ""),  "(", ""), ")", "") ``` 6. Click **Done**. ### Step 4: Retrieve the consent records (Get Records) This element retrieves every consent record for the contact's number, across all of the Natterbox-owned numbers it may be paired with. 1. Click the **+** icon after the Start element and select **Get Records**. 2. Label: `Get Consent Record`. 3. Object: `Natterbox Consent` (`nbavs__Consent__c`). 4. Filter Natterbox Consent Records (All Conditions Are Met): - Field: `nbavs__ExternalAddress__c` - Operator: `Equals` - Value: `{!forExternalAddress}` 5. How Many Records to Store: **All records**. 6. How to Store Record Data: **Automatically store all fields**. 7. Click **Done**. ### Step 5: Add a Decision element The Decision element determines which path to follow based on the current value of the Do Not Call field. 1. Click the **+** icon after the Get Records element and select **Decision**. 2. Label: `Check Do Not Call Value` (the API Name auto-populates). 3. Configure the first outcome: - Label: `Do Not Call is True` - Condition Requirements: **All Conditions Are Met (AND)** - Resource: `{!$Record.DoNotCall}` - Operator: `Equals` - Value: `{!$GlobalConstant.True}` 4. Rename the **Default Outcome** to `Do Not Call is False`. 5. Click **Done**. ### Step 6: Opt Out path (loop and update) Under the **Do Not Call is True** outcome, loop through the consent records and opt out each one that is not already opted out. 1. Under the **Do Not Call is True** outcome, click the **+** icon and select **Loop**. 2. Label: `Loop for all consent records`. 3. Collection Variable: `{!Get_Consent_Record}`. 4. Direction: **First item to last item**. Click **Done**. 5. Inside the loop, on the **For Each** path, click the **+** icon and select **Decision**. 6. Label: `Check if record needs updating`. Configure the first outcome: - Label: `Record needs updating` - Condition Requirements: **All Conditions Are Met (AND)** - Resource: `{!Loop_for_all_consent_records.nbavs__Status__c}` - Operator: `Equals` - Value: `Opt In` 7. Rename the **Default Outcome** to `No change to record`, then click **Done**. Records that are already opted out follow this path and are left untouched. 8. Under the **Record needs updating** outcome, click the **+** icon and select **Update Records**. 9. Label: `Update Consent to Opt Out`. 10. How to Find Records to Update and Set Their Values: **Specify conditions to identify records, and set fields individually**. 11. Object: `Natterbox Consent` (`nbavs__Consent__c`). 12. Filter Natterbox Consent Records (All Conditions Are Met): - Field: `Id` - Operator: `Equals` - Value: `{!Loop_for_all_consent_records.Id}` 13. Set Field Values for the Natterbox Consent Records: - `nbavs__Status__c` - Value: `Opt Out` - `nbavs__Temporary__c` - Value: `{!$GlobalConstant.False}` - `nbavs__ConsentEndTime__c` - Value: `{!$Flow.CurrentDateTime}` 14. Click **Done**. ### Step 7: Opt In path (loop and update) Under the **Do Not Call is False** (Default) outcome, loop through the consent records and permanently opt in each one that is not already permanently opted in. 1. Under the **Do Not Call is False** outcome, click the **+** icon and select **Loop**. 2. Label: `Loop for all consent records`. 3. Collection Variable: `{!Get_Consent_Record}`. 4. Direction: **First item to last item**. Click **Done**. 5. Inside the loop, on the **For Each** path, click the **+** icon and select **Decision**. 6. Label: `Check if record needs updating`. Configure the first outcome: - Label: `Record needs updating` - Condition Requirements: **Any Condition Is Met (OR)** - Row 1: `{!Loop_for_all_consent_records.nbavs__Status__c}` `Does Not Equal` `Opt In` - Row 2: `{!Loop_for_all_consent_records.nbavs__Temporary__c}` `Equals` `{!$GlobalConstant.True}` - Row 3: `{!Loop_for_all_consent_records.nbavs__ConsentEndTime__c}` `Is Null` `{!$GlobalConstant.False}` 7. Rename the **Default Outcome** to `No change to record`, then click **Done**. Records that are already permanently opted in follow this path and are left untouched. 8. Under the **Record needs updating** outcome, click the **+** icon and select **Update Records**. 9. Label: `Update Consent to Opt In`. 10. How to Find Records to Update and Set Their Values: **Specify conditions to identify records, and set fields individually**. 11. Object: `Natterbox Consent` (`nbavs__Consent__c`). 12. Filter Natterbox Consent Records (All Conditions Are Met): - Field: `Id` - Operator: `Equals` - Value: `{!Loop_for_all_consent_records.Id}` 13. Set Field Values for the Natterbox Consent Records: - `nbavs__Status__c` - Value: `Opt In` - `nbavs__Temporary__c` - Value: `{!$GlobalConstant.False}` - `nbavs__ConsentEndTime__c` - add the field and leave the value **blank** to clear it (permanent consent has no end time). 14. Click **Done**. > [!NOTE] > Why loop instead of a single bulk update? > > Looping lets the flow evaluate each consent record on its own and only update the ones that actually need changing, using the **Check if record needs updating** decision. Records already in the correct state take the **No change to record** path, which avoids unnecessary record updates and keeps the automation efficient when a contact has several pairings. ### Step 8: Add fault paths (recommended) Add a fault path to each Update Records element so that failures are handled gracefully rather than causing the whole transaction to roll back silently. 1. Hover over an **Update Records** element and click the **+** on the **Fault** connector. 2. Add an action to record or surface the error, for example a **Create Records** element that logs the fault, or an email alert to an administrator. 3. Repeat for the second Update Records element. > [!NOTE] > If no consent record matches > > The **Get Records** element filters by phone number. If a contact has no consent record for that number yet, the returned collection is empty, the loop runs zero times, and nothing is updated. This is expected: a consent record is created the first time a conversation takes place on that number pairing. ### Step 9: Save and activate the flow 1. Click **Save**. 2. Enter a Flow Label, for example `Update Natterbox Consent on Do Not Call Change`. 3. Click **Save**. 4. Once saved, click **Activate** to make the flow live. ## Understanding multiple consent records A single contact can have several consent records, because consent is stored per phone-number pairing. Multiple records can exist when: - The customer has been contacted on more than one of their own numbers (for example, mobile and landline). - Your organisation uses more than one Natterbox-owned number (for example, a sales line and a support line), so the same customer number is paired with each. The **Get Records** element retrieves every consent record whose External Address matches the contact's number, regardless of which Natterbox-owned number it is paired with. The **Loop** then processes each record in turn, and the **Check if record needs updating** decision ensures only the records that require a change are updated. > [!WARNING] > Matching more than one customer number > > This flow matches a single contact phone field (`MobilePhone` in the example formula). If a contact can be reached on several of their own numbers and you want to update the consent records for all of them, create a formula for each number and expand the Get Records filter using **Any Condition Is Met (OR)**. Speak with your Natterbox administrator about your specific requirements. ## Testing the flow Test the automation in a sandbox or on test data before relying on it in production. 1. Identify a Contact whose phone number matches the `nbavs__ExternalAddress__c` of one or more existing consent records. 2. Open the Contact, tick the **Do Not Call** checkbox, and save. 3. Open the related Natterbox Consent records and confirm that Status is `Opt Out`, Temporary is unchecked, and Consent End Time is populated with the current date and time. 4. Edit the Contact again, untick **Do Not Call**, and save. 5. Confirm the consent records now show Status `Opt In`, Temporary unchecked, and Consent End Time empty. 6. If the contact has multiple matching consent records, verify that all of them were updated. You can inspect the records directly in the Developer Console with a query such as: ```sql SELECT Id, nbavs__ExternalAddress__c, nbavs__InternalAddress__c,       nbavs__Status__c, nbavs__Temporary__c, nbavs__Active__c,       nbavs__ConsentStartTime__c, nbavs__ConsentEndTime__c FROM nbavs__Consent__c WHERE LastModifiedDate = TODAY ``` > [!NOTE] > Debugging tip > > If the flow does not appear to fire, open it in **Setup → Flows** and use **Debug** to run it against a specific Contact. Check **Setup → Process Automation → Paused and Failed Flow Interviews** for errors. ## Troubleshooting | Issue | Possible cause | Solution | | --- | --- | --- | | Flow does not fire when Do Not Call changes | The flow is not activated, or the entry-condition formula has a syntax error. | Confirm the flow is active and that the formula reads exactly `ISCHANGED({!$Record.DoNotCall})`. | | Consent records are not updated | The Get Records element returned nothing because the contact's phone number does not match the stored External Address format. | Compare the value of your `forExternalAddress` formula against a real `nbavs__ExternalAddress__c` value. They must be identical digits, including country code and no plus sign. | | Consent processing breaks after an opt out | The record was set to Opt Out with Temporary unchecked but no Consent End Time. | Ensure the Opt Out path sets `nbavs__ConsentEndTime__c` to `{!$Flow.CurrentDateTime}`. Correct any affected records. | | Only some consent records are updated | The Get Records filter matched only one pairing, or some records took the No change to record path. | Confirm the External Address on each pairing matches the normalised number, and review the Check if record needs updating conditions. | | Status value not accepted | The picklist value does not exactly match the values on the Consent object. | Confirm the values under **Object Manager → Natterbox Consent → Fields & Relationships → Status**. They should be `Opt In` and `Opt Out`. | ## Related - [Salesforce Automated Messages](/salesforce-automated-messages.md) - [7.2.1. Consent Management](/messaging-consent-management.md) - [Keywords & Consent](/keywords-consent.md)