Braze

Overview

Use the following as an addendum to the Braze integration documentation for using Lob with Braze.

This integration will allow customers to send data from Braze to Lob. A pre-designed webhook can then be used within a campaign to trigger mail to customers. After sending through Braze, the mail data can be accessed from within the Lob dashboard.

Step 1 - Add Custom Attributes

Add Custom Attributes for user mailing address information:

  • address_line1

  • address_line2

  • address_city

  • address_state

  • address_zip

  • address_country

Step 2 - Update user profiles

Update user profiles with mailing addresses.

Import CSV:

API call:

Anything highlighted is a custom variable that will need to be updated for each customer or use case.

curl -X POST \
  https://rest.iad-01.braze.com/users/track \
  -H 'Content-Type: application/json' \
  -d '{
    "api_key": "Braze_API_Key",
    "attributes": [
      {
          "external_id" : "10142019",
          "address_line1" : "185 BERRY ST STE 6100",
          "address_line2" : null,
          "address_city" : "SAN FRANCISCO",
          "address_state" : "CA",
          "address_zip" : "94107-1741",
          "address_country" : "UNITED STATES"
      }
     ]
   }'

Step 3 - Create a webhook template

Create a webhook template (Braze Documentation). Once this template is made it can be used for your future campaigns as well. In the case that you have different variations of sends, meaning you are going to perform one send with postcards and one with letters it is recommended that you create 2 separate webhook templates in Braze for this.

Additionally, if you are going to be doing small variations such as sending first-class vs standard class depending on the recipient, then you can leverage Braze's conditional logic. You can build this logic into the template and have one webhook template support multiple variations.

Example postcard

Compose tab:

Webhook URL: https://api.lob.com/v1/postcards

Request body: Raw Text

Braze's default webhook template does not include the opening and closing {} brackets, so ensure those have been added before saving.

{
    "description" : "{{campaign.${name}}}",
    "metadata" : {
        "campaign" : "{{campaign.${name}}}"
    },
    "to" : {
        "name" : "{{${first_name}}} {{${last_name}}}",
        "address_line1" : "{{custom_attribute.${address_line1}}}",
        "address_line2" : "{{custom_attribute.${address_line2}}}",
        "address_city" : "{{custom_attribute.${address_city}}}",
        "address_state" : "{{custom_attribute.${address_state}}}",
        "address_zip" : "{{custom_attribute.${address_zip}}}"
    },
    "from" : "adr_2066448bdef840f1",
    "front" : "tmpl_8b3b1249ede0406",
    "back" : "tmpl_d69077c7be7bd09",
    "merge_variables" : {
        "name" : "{{${first_name}}}"
    }
}

Example letter

Compose tab:

Webhook URL: https://api.lob.com/v1/letters

Request body: Raw Text

{
    "description" : "{{campaign.${name}}}",
    "to" : {
        "name" : "{{${first_name}}} {{${last_name}}}",
        "address_line1" : "{{custom_attribute.${address_line1}}}",
        "address_line2" : "{{custom_attribute.${address_line2}}}",
        "address_city" : "{{custom_attribute.${address_city}}}",
        "address_state" : "{{custom_attribute.${address_state}}}",
        "address_zip" : "{{custom_attribute.${address_zip}}}"
    },
    "from" : "adr_2066448bdef840f1",
    "file" : "tmpl_d69077c7be7bd09",
    "color" : "true",
    "merge_variables" : {
        "name" : "{{${first_name}}}"
    },
    "metadata" :
        "campaign" : "{{campaign.${name}}}",
        "zip" : "{{custom_attribute.${address_zip}}}"
    },
    "mail_type" : "usps_first_class",
    "double_sided": false,
    "address_placement": "top_first_page",
    "mail_type": "usps_first_class",
    "return_envelope": true,
    "perforated_page": 1,
    "extra_service": "registered",
    "custom_envelope": null,
    "billing_group_id" : ""
}

Example self-mailer

Compose tab:

Webhook URL: https://api.lob.com/v1/self_mailers

Request body: Raw Text

{
    "description" : "{{campaign.${name}}}",
    "size" : "6x18_bifold",
    "to" : {
        "name" : "{{${first_name}}} {{${last_name}}}",
        "address_line1" : "{{custom_attribute.${address_line1}}}",
        "address_line2" : "{{custom_attribute.${address_line2}}}",
        "address_city" : "{{custom_attribute.${address_city}}}",
        "address_state" : "{{custom_attribute.${address_state}}}",
        "address_zip" : "{{custom_attribute.${address_zip}}}"
    },
    "from" : "adr_2066448bdef840f1",
    "inside" : "tmpl_8b3b1249ede0406",
    "outside" : "tmpl_d69077c7be7bd09",
    "merge_variables" : {
        "name" : "{{${first_name}}}"
    },
    "metadata" :
        "campaign" : "{{campaign.${name}}}",
        "zip" : "{{custom_attribute.${address_zip}}}"
    },
    "mail_type" : "usps_first_class",
    "billing_group_id" : ""
}

Settings tab

Be sure to leave the : after the Lob API key you paste in between the apostrophes.

REQUEST HEADERS:

  • Authorization: Basic {{ 'YOUR_LOB_API_KEY:' | base64_encode }}

  • Content-Type: application/json

  • Idempotency-Key: {{${user_id}}}

    • It is recommended that you leverage idempotency keys to prevent duplication of mail being sent. It can be any value you seem fit but often it is userID or a combination of userID and campaign name.

  • HTTP METHOD: POST

Step 4 - Test your new webhook

Test your new webhook template and check your Lob dashboard to ensure desired results. It is recommended to run a one-off test in Braze to see if the request format is set up appropriately and then run a full end-to-end test where you send an entire campaign through your test environment.

Running a one-off test

When running a one-off test it is useful to have test users in your system who have the correct data needed to send mail and validate your creatives. Here is an example of a test we would perform.

Common errors

  1. 401 Unauthorized

    • If you receive this error message, your API key is incorrect.

  2. 422 Unprocessable Entity (Invalid request payload JSON format)

    • If you receive this error, it is likely that your payload is not formatted correctly. It needs to match JSON formatting.

    • Generally speaking, the rules that are often broken are:

      1. All keys and values are enclosed in double quotes (").

      2. Commas after every key-value pair except for the last one.

      3. No newline characters in any values and no extra spaces between fields.

  3. 422 Unprocessable Entity (Other)

    • Other than JSON errors, you can receive 422 errors in the payload sent to Lob does not match our requirements.

    • For example, if you are missing address_line1 in the payload you will get an error saying that is needed. For these errors, you can make the appropriate adjustments and retry your requests.

The "testing" functionality in Braze is sending a one-off request to Lob, this means if you have your LIVE API key in the template it will create mail and if you have your test key it will not.

Make sure when you are testing that your cancellation windows are set to an ample time (2 hours is recommended) to make sure you can always cancel mail if you make a mistake.

FAQs

How do I use merge variables from Braze?

To leverage merge variables, in Braze you will reference the merge variable in your HTML file as the Key and the user attribute as the value.

For example, if you had a merge variable called f_name in your HTML, then in the section of your payload called merge_variables you would have a key of f_name and a value of the user attribute in Braze. Here is an example of what that would look like in Braze

"merge_variables" : {
    "f_name" : "{{${first_name}}}"
}

What do I use for the file parameter for letters? What do I use for the front and back parameters for postcards?

See more information on file format types here

Essentially you can either host your HTML in the Lob platform where you can then reference the template ID that is created for you, or you can leverage Braze’s Media Library where you will be provided with a URL that can be used as the value for these parameters.

Here is an example of what you could see in Braze:

"file" : "tmpl_3v234vl23hj5v"
"file" : "https://braze-images.com/appboy/communication/assets/image_assets/images/25660da30cdc28a314/original.jpg?1637006884"

Capturing Lob webhook data in Braze

Braze’s Data Transformation tool enables you to capture webhook events from Lob, and use them to either update Attributes or create Events within Braze.

Steps:

  1. Set up a Data Transformation in Braze. This will generate a Webhook URL you can use to pass events into Braze.

  2. Create Lob Webhook for the events you want to track, using the Braze-provided URL

  3. Set up the Transformation Code in Braze to listen for the event. You can use this to either update an Attribute or generate an Event.

    • See Example 1 below for a 'Letter Viewed' example, in which it both updates an attribute within Braze and creates an Event.

  4. Send a Test webhook and check the resulting Output to ensure the data is successfully being captured, and the subsequent attribute/event updates are occurring within Braze

Example 1: Braze Transformation Code for Letter Viewed, which updates the attribute 'external_id' and generates an Event named 'Letter Viewed' when the webhook from Lob is received:

let brazecall = {
 "attributes": [
   {
     "external_id": payload.body.metadata.external_id,
     "_update_existing_only": true
   }
 ],
 "events": [
   {
     "external_id": payload.body.metadata.external_id,
     "_update_existing_only": true,
     "name": "Letter Viewed",
     "campaign": payload.body.description,
     "time": new Date().toISOString(),
     "properties": {
       "property_1": payload.event_type
     }
   }
 ]
};

Example 2: Braze transformation output after webhook received, showing the updated attribute 'external_id' and creating the Event 'Letter Viewed'.

{
  "attributes": [
    {
      "external_id": "123456789",
      "_update_existing_only": true
    }
  ],
  "events": [
    {
      "external_id": "123456789",
      "_update_existing_only": true,
      "name": "Letter Viewed",
      "campaign": "Lob Braze Webhook Demo",
      "time": "2023-10-05T23:14:58.073Z",
      "properties": {
        "property_1": {
          "enabled_for_test": true,
          "id": "letter.viewed",
          "object": "event_type",
          "resource": "letters"
        }
      }
    }
  ]
}
Success. Output is a valid /users/track request.
Details:
{
  "attributes_validated": 1,
  "events_validated": 1,
  "message": "success"
}

Advanced logic

Idempotent requests

Rate limiting

Last updated