Hooks

Hooks let you trigger actions when a contact replies to a campaign send. They extend your campaigns with automated follow-ups or integrations.

Currently, Dripcel supports two hook types:

  • SMS Hook

  • Webhook


SMS Hook

An SMS Hook automatically sends an SMS when a contact replies to a campaign.

Options:

  • Content – The text of the SMS to send.

  • Destinations – A comma-separated list of phone numbers to send the SMS to.

  • Send to Replying Contact – If checked, the SMS will be sent directly to the contact who replied.

You can use both options together — sending the SMS to the replying contact and to the additional phone numbers in Destinations.


Webhook

A Webhook Hook sends an HTTP request to a specified URL when a contact replies. This is commonly used to integrate with external systems (e.g., CRMs, analytics, or custom apps).

Options:

  • URL – The destination URL for the request.

  • Method – HTTP method: GET or POST.

  • Body – JSON body to send. You can insert templates to include contact, campaign, reply, or send data.

  • Encode Into URL – If checked, the JSON body is encoded into URL query parameters instead of being sent in the request body.

  • Headers – Custom HTTP headers in valid JSON format.

Example:
JSON body:

{ "name": "{{contact.firstname}}" }

Encoded into URL →

https://example.com?name=John


Retry Policy & Duplicate Handling

  • Dripcel retries failed webhooks up to 3 times, with a 10-second timeout each.

  • Your system must handle duplicate requests.

  • Use the dripcel-idempotency-key header to identify retries — it is identical for all attempts of the same webhook.


Templates in Webhooks

Templates work like campaign content templates ({{template}}). They allow you to insert live data into webhook payloads.

Available Objects

Contact

Contains all default and custom fields, plus metadata.

type Contact = { _id: string; cell: string; firstname?: string; lastname?: string; idnumber?: string; email?: string; c1?: unknown; // depends on custom field type ... c10?: unknown; tag_ids: string[]; validated?: { at: Date; reachable: boolean }; createdAt: Date; };

Reply

Information about the reply message.

type Reply = { To: string; // number message was sent from Message: string; // reply content Msisdn: string; // replying contact’s number Received: Date; // timestamp of reply campaign_id?: string; kind: "optOut" | "optIn" | "unknown"; };

Campaign

The campaign associated with the reply.

type Campaign = { _id: string; name: string; createdAt: Date; tag_ids: string[]; segment_ids: string[]; incomePerLead?: number; defaultSaleValue?: number; };

Send

The original send that triggered the reply.

type Send = { _id: string; campaign_id?: string; message: string; triggeredBy: string; startDeliveryAt: string; destinations: undefined; // see GET /send-logs for details };

Other

  • now – the current date/time.


Example

Webhook body with templates:

{ "name": "{{contact.firstname}}", "message": "{{reply.Message}}", "campaign": "{{campaign.name}}", "send_id": "{{send._id}}" }

Webhook output after substitution:

{ "name": "John", "message": "Hello", "campaign": "My Campaign", "send_id": "5f9b3b7b7b7b7b7b7b7b7b7b" }


Template Options

  • Date Formatting: {{reply.Received|date:yyyy-MM-dd}}2025-10-03

  • Cell Formatting:

    • cell:local0821234567

    • cell:plus+27821234567

    • cell:trailing821234567

    • Default → MSISDN (27821234567)

  • Fallback Values: {{contact.firstname?Unknown}}Unknown if field missing


Combined Example

{ "name": "{{contact.firstname?Unknown}}", "cell": "{{contact.cell|cell:local}}", "message": "{{reply.Message}}", "campaign": "{{campaign.name}}", "date": "{{reply.Received|date:yyyy-MM-dd?Unknown}}" }