1. Wiki
  2. Features

Webhooks: push every send to your system

With every campaign send, push the contact's data to your CRM or your team chat. No coding, with testing, retries and logs.

Quick answer

In Webhooks, create a webhook with method, URL, headers and a JSON body with variables such as {{ lead.name() }}. Test it with a sample contact, attach up to 3 webhooks to an email campaign (or use webhooks only) and track every delivery in the logs. If the destination fails, BIP tries up to 6 times, every 60 seconds.

EffortNo-codeChannelWebhookPlanFree

Every time a campaign reaches a contact, BIP can notify another system: create the contact in your CRM, post a message for your team, feed a spreadsheet. You build the request once in the panel, with the contact's data in the right place, and BIP does the rest with every send.

What you need

  • A BIP account (the free plan works)
  • The URL that will receive the data, plus the access token if the destination requires one
  • An email campaign, recurring, one-time or API-triggered, to attach the webhook to

What you'll get

  • Every contact in the campaign lands in your CRM or tool, with the name, email, phone, city, fields and KPIs you choose.
  • Everything in the panel, no code: method, URL, headers and body, with variable suggestions and a preview.
  • Deliveries that recover on their own: if the destination fails, BIP tries again.
  • Logs with the request and response for every delivery, plus metrics per webhook.
  • Webhook-only campaigns, to sync systems without sending email.

How it works

  1. 1Create the webhook with URL, headers and body
  2. 2Test it with a sample contact and check the log
  3. 3Attach it to a campaign: every processed contact fires the webhook

A webhook is an HTTP request that BIP makes to your system. You define the method, the URL, the headers and the JSON body. In the body, variables such as {{ lead.name() }} turn into each contact's data at send time.

The webhook runs when it's attached to a campaign. For each contact the campaign processes, BIP builds the body with that person's data and sends it. It works with One-time, Recurring and API Trigger campaigns. People who unsubscribed from all communications don't fire the webhook.

A delivery succeeds when your system responds with a 2xx code (200, 201, 204…). Any other response, or no response at all, triggers a retry 60 seconds later. There are up to 6 attempts in total: the first one plus 5 more.

Step by step

1. Create the webhook

  1. In the menu, open Webhooks and click New Webhook. BIP creates an [untitled] webhook and opens its page.
  2. In Webhook Configuration, choose the method. To send the contact's data, use POST (or PUT, if the destination requires it).
  3. Paste the URL that will receive the data in place of http://your-webhook-endpoint.com.
  4. Click Save.
dash.bip.marketing/…/webhooks/…
Webhook page with method and URL in Webhook Configuration

Screenshot coming soon

Webhook page with method and URL in Webhook Configuration

2. Build the headers and the body

  1. Open Headers and write a JSON object. Always include "Content-Type": "application/json": BIP sends the body as JSON and most systems check this header. If the destination requires a token, add it too, for example "Authorization": "Bearer YOUR_TOKEN".
  2. In Body Template, write the JSON the destination expects. Inside a quoted value, type {{ and pick the variable from the suggestion list. The help icon next to Body Template shows every variable.
  3. Check the Preview on the right: it shows the finished body, filled in with a sample contact's data, and updates right after you stop typing.
  4. Click Save.

The body must be valid JSON to save. That's why every variable goes inside quotes and reaches the destination as text: "vip": "{{ lead.hasTag('vip') }}" becomes "vip": "true".

For a fallback value when the data is empty, use ||: "saudacao": "Hi, {{ lead.firstName() || 'there' }}".

dash.bip.marketing/…/webhooks/…
Webhook headers, body template with variables and preview

Screenshot coming soon

Webhook headers, body template with variables and preview

3. Name and organize it

  1. At the top of the page, click Settings.
  2. Fill in the Name (it's what you see when attaching it to campaigns), choose an icon and, if you like, add a Description.
  3. In Group, choose a group to organize the list. Webhook groups are created in Settings → Groups.
  4. In Status, leave Active on.
  5. Click Save.
dash.bip.marketing/…/webhooks/…
Webhook settings with name, icon, description, group and status

Screenshot coming soon

Webhook settings with name, icon, description, group and status

4. Test it with a sample contact

  1. With everything saved, click Test Webhook. The button is available when there are no unsaved changes.
  2. BIP sends a real request to your URL, with a sample contact (made-up name, email, phone and cities; empty custom fields), and opens Webhook Stats.
  3. In Delivery Logs, click View on the test row. Request shows what BIP sent; Response shows the code and body your system returned.

The test really reaches your system. If the destination is your production CRM, delete the test record afterwards, or point the webhook at a test environment first.

dash.bip.marketing/…/webhooks/stats/…
Webhook stats with the delivery log for the test

Screenshot coming soon

Webhook stats with the delivery log for the test

5. Attach it to a campaign

  1. In Campaigns, open a campaign or click New Campaign, with Email as the Channel.
  2. In the Webhooks section, select up to 3 webhooks. Every processed contact fires all of them.
  3. For a webhook-only campaign, don't choose an Email Template and select at least one webhook. No email goes out: each contact only fires the webhooks.
  4. Choose the Schedule Type (One-time, Recurring or API Trigger), then save and activate it like any other campaign.
dash.bip.marketing/…/campaigns/…
Webhooks section of an email campaign with webhooks selected

Screenshot coming soon

Webhooks section of an email campaign with webhooks selected

BIP Full only

In Flows, the Send Webhook step uses the same webhooks: the contact fires the webhook when it reaches that point in the flow.

Reference

Webhook configuration

OptionHow it works
MethodGET, POST, PUT or DELETE. To send data in the body, use POST or PUT.
URLDestination address. Fixed: it doesn't accept variables.
HeadersJSON object, such as {"Content-Type": "application/json"}. Fixed.
Body TemplateValid JSON, with contact variables inside quotes.
Name, iconHow the webhook appears in the list and in campaigns.
DescriptionFree text, for your team.
GroupOrganizes the Webhooks list.
StatusActive or inactive.

Delivery and retries

RuleValue
SuccessResponse with a 2xx code
RetryAny other code, or no response
Interval60 seconds
Total attempts6 (the first one plus 5 more)
After the 6th failureThe campaign logs a webhook error for that contact
Webhooks per campaignUp to 3, in Email channel campaigns, with or without email

Contact variables

Use them inside a quoted value. The result arrives as text.

VariableWhat it returns
{{ lead.name() }}Full name
{{ lead.firstName() }}First name
{{ lead.middleName() }}Middle names
{{ lead.lastName() }}Last name
{{ lead.email() }}Email
{{ lead.id() }}Contact ID in BIP
{{ lead.namespace() }}Account namespace
{{ lead.createdAt() }}Creation date, in ISO 8601 format
{{ lead.createdAt('YYYY-MM-DD') }}Formatted creation date
{{ lead.updatedAt() }}Last update, in ISO 8601 format
{{ lead.updatedAt('YYYY-MM-DD') }}Formatted last update
{{ lead.metadata('[METADATA_KEY]') }}One metadata value: replace [METADATA_KEY] with the key
{{ lead.sourceType('first') }}First source type (api, internal, page…)
{{ lead.sourceType('last') }}Last source type

Phone variables

VariableExample
{{ lead.phone('e164') }}+5511912345678
{{ lead.phone('international') }}+55 11 91234-5678
{{ lead.phone('national') }}(11) 91234-5678
{{ lead.phone('nationalNumber') }}11912345678
{{ lead.phone('countryCallingCode') }}55
{{ lead.phone('countryCode') }}BR
{{ lead.phone('numberType') }}MOBILE
{{ lead.phone('uri') }}tel:+5511912345678
{{ lead.maskedPhone('e164', '(999) 999-9999') }}Phone in the mask you define

In the mask, each 9 is a digit, filled in from left to right. For the Brazilian format, use {{ lead.maskedPhone('national', '(99) 99999-9999') }}.

Location variables

VariableWhat it returns
{{ lead.location('last', 'city') }}City of the last location
{{ lead.location('last', 'region') }}State or region of the last location
{{ lead.location('last', 'country') }}Country of the last location
{{ lead.location('last', 'timezone') }}Time zone of the last location
{{ lead.location('last', 'latitude') }}Latitude of the city center
{{ lead.location('last', 'longitude') }}Longitude of the city center

Replace last with first for the first location. The location is always the city.

Opt-out variables

VariableWhat it returns
{{ lead.unsubscribed() }}true if the person unsubscribed from all communications
{{ lead.unsubscribedFromChannel('email') }}true if they unsubscribed from email
{{ lead.unsubscribedFromChannel('whatsapp') }}true if they unsubscribed from WhatsApp

Your account's variables

The editor builds these variables from your custom fields, KPIs and tags. In the suggestion list, they show up with the name you gave them.

VariableFor
{{ lead.field('Field name') }}String, Number, Boolean and Date fields
{{ lead.dateField('Field name', 'YYYY-MM-DD') }}Date field, in the format you choose
{{ lead.ageField('Field name') }}Age in years, from a Date field
{{ lead.locationField('Field name', 'city') }}Location field (also region, country, timezone, latitude, longitude)
{{ lead.phoneField('Field name', 'e164') }}Phone field (also the formats in the phone table)
{{ lead.maskedPhoneField('Field name', 'e164', '(999) 999-9999') }}Phone field with a mask
{{ lead.maskedNumberField('Field name', '999 999 999 99') }}Number field with a mask
{{ lead.kpi('KPI name') }}Value of a KPI
{{ lead.hasTag('Tag name') }}true if the contact has the tag

Ready to copy

Send every contact to a CRM

Agência Pulso sends every person who receives the welcome campaign to its CRM. Adjust the key names to what your CRM expects.

Headers
{
  "Content-Type": "application/json",
  "Authorization": "Bearer YOUR_CRM_TOKEN"
}
Body Template
{
  "nome": "{{ lead.name() }}",
  "email": "{{ lead.email() }}",
  "telefone": "{{ lead.phone('e164') }}",
  "cidade": "{{ lead.location('last', 'city') }}",
  "estado": "{{ lead.location('last', 'region') }}",
  "origem": "bip",
  "id_bip": "{{ lead.id() }}",
  "criado_em": "{{ lead.createdAt('YYYY-MM-DD') }}"
}
SettingValue
MethodPOST
URLYour CRM's contact-creation endpoint
CampaignEmail channel, with or without an Email Template
WebhooksThis webhook (up to 3 per campaign)

To send each person to the CRM the moment they sign up, with no email: create a campaign with only this webhook, set to API Trigger in Immediate mode, and trigger it through the API whenever someone signs up.

Notify your team

Many chat and automation tools take messages through an incoming webhook, with the text in the text field. Imobiliária Marés alerts its agents about every person who enters the launch campaign.

Headers
{
  "Content-Type": "application/json"
}
Body Template
{
  "text": "New lead: {{ lead.name() }} | {{ lead.email() || 'no email' }} | {{ lead.phone('international') || 'no phone' }} | {{ lead.location('last', 'city') || 'city not provided' }}"
}

Check which text field your destination tool expects and replace text if needed.

How to measure

  • Webhook Stats: in the Webhooks list, open the webhook and click View Stats. You see Total Requests, Successful, Failed, Avg Response Time, Success Rate, Retry Rate, Error Rate, Status Codes and the Delivery Breakdown. The numbers update Live.
  • Delivery Logs: filter by From Date, To Date and Limit. Each row shows Date, Status, URL, Method and Attempts; under View, you see the full Request and Response.
  • In the campaign: in View Stats, Webhook Delivery and Webhook Errors show the campaign totals, and Recipient Interactions shows the webhook for each contact.
  • A high Retry Rate means the destination is slow or unstable. Open the Response in the logs to see why.

Frequently asked questions

What counts as a successful delivery?

A response with a 2xx code. Any other code, or no response, triggers a retry 60 seconds later, up to 6 attempts in total. After the sixth failure, the campaign logs the error for that contact.

Does a webhook count as a send?

In an email campaign with webhooks, the send for that contact counts once: webhooks don't add to it. In a webhook-only campaign, each processed contact counts as one send, just like an email. Test Webhook doesn't count.

Can I use variables in the URL or the headers?

No. The URL and the headers are fixed. Contact variables work in the Body Template.

Does the test reach my system?

Yes. Test Webhook makes a real request, with a sample contact. Use a test environment or delete the record afterwards.

See also