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.
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
- 1Create the webhook with URL, headers and body
- 2Test it with a sample contact and check the log
- 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
- In the menu, open Webhooks and click New Webhook. BIP creates an [untitled] webhook and opens its page.
- In Webhook Configuration, choose the method. To send the contact's data, use POST (or PUT, if the destination requires it).
- Paste the URL that will receive the data in place of
http://your-webhook-endpoint.com. - Click Save.

Screenshot coming soon
2. Build the headers and the body
- 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". - 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. - 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.
- 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' }}".

Screenshot coming soon
3. Name and organize it
- At the top of the page, click Settings.
- Fill in the Name (it's what you see when attaching it to campaigns), choose an icon and, if you like, add a Description.
- In Group, choose a group to organize the list. Webhook groups are created in Settings → Groups.
- In Status, leave Active on.
- Click Save.

Screenshot coming soon
4. Test it with a sample contact
- With everything saved, click Test Webhook. The button is available when there are no unsaved changes.
- 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.
- 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.

Screenshot coming soon
5. Attach it to a campaign
- In Campaigns, open a campaign or click New Campaign, with Email as the Channel.
- In the Webhooks section, select up to 3 webhooks. Every processed contact fires all of them.
- 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.
- Choose the Schedule Type (One-time, Recurring or API Trigger), then save and activate it like any other campaign.

Screenshot coming soon
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
| Option | How it works |
|---|---|
| Method | GET, POST, PUT or DELETE. To send data in the body, use POST or PUT. |
| URL | Destination address. Fixed: it doesn't accept variables. |
| Headers | JSON object, such as {"Content-Type": "application/json"}. Fixed. |
| Body Template | Valid JSON, with contact variables inside quotes. |
| Name, icon | How the webhook appears in the list and in campaigns. |
| Description | Free text, for your team. |
| Group | Organizes the Webhooks list. |
| Status | Active or inactive. |
Delivery and retries
| Rule | Value |
|---|---|
| Success | Response with a 2xx code |
| Retry | Any other code, or no response |
| Interval | 60 seconds |
| Total attempts | 6 (the first one plus 5 more) |
| After the 6th failure | The campaign logs a webhook error for that contact |
| Webhooks per campaign | Up to 3, in Email channel campaigns, with or without email |
Contact variables
Use them inside a quoted value. The result arrives as text.
| Variable | What it returns |
|---|---|
{{ lead.name() }} | Full name |
{{ lead.firstName() }} | First name |
{{ lead.middleName() }} | Middle names |
{{ lead.lastName() }} | Last name |
{{ lead.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
| Variable | Example |
|---|---|
{{ 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
| Variable | What 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
| Variable | What 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.
| Variable | For |
|---|---|
{{ 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.
{
"Content-Type": "application/json",
"Authorization": "Bearer YOUR_CRM_TOKEN"
}{
"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') }}"
}| Setting | Value |
|---|---|
| Method | POST |
| URL | Your CRM's contact-creation endpoint |
| Campaign | Email channel, with or without an Email Template |
| Webhooks | This 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.
{
"Content-Type": "application/json"
}{
"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.