Courier

Courier routes notifications across email, SMS, push, chat and in-app. Datafly Signal calls the Courier Send API (POST /send) so an event such as a sign-up or an order sends a Courier template to the visitor, with the event properties as template data.

Why route Courier through Datafly Signal

  • Events come from your server, not the browser. They reach Courier even when a tracker blocker or a failed page unload would have dropped a client-side call.
  • Delivery is queued and retried. Signal buffers to Kafka and retries on 429 or a transient failure rather than dropping the event; a permanent rejection goes to the dead-letter queue with the vendor’s reason.
  • One consent decision governs every destination. Courier is gated by the same consent state as the rest of your stack, so a withdrawal applies everywhere at once.

Get your Courier credentials

Create an API key

In Courier open Settings > API Keys (app.courier.com/settings/api-keys) and copy a production key.

Create the templates

Create a template for each event you send and give it the alias shown under Presets (signed_up, order_completed, order_refunded …). Or set Default Template ID to send one template for every event.

Configuration

FieldRequiredDescription
api_keyYesYour Courier server-side API key, sent as a Bearer token. Find it in Courier under Settings > API Keys (app.courier.com/settings/api-keys). Never expose this in client-side code.
template_idNoOptional. A Courier template (notification) id or alias that every event sends. Leave blank to send each event to the template whose alias is the event name (signed_up, order_completed, order_refunded …): create those aliases in Courier.

Management UI setup

  1. Go to Integrations in the sidebar and open the Integration Library tab.
  2. Find Courier under Marketing Automation and click Install.
  3. Choose a preset, enter the fields above and click Install Integration.

Management API setup

curl -X POST http://localhost:8084/v1/admin/integration-catalog/courier/install \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
  "name": "Courier",
  "variant": "default",
  "config": {
    "api_key": "your_api_key"
  },
  "delivery_mode": "server_side"
}'

What Signal sends

An example request, rendered from the default preset for purchase:

POST https://api.courier.com/send
Idempotency-Key: 3f1c2a90-7d4e-4b8a-9c61-2f0e5d7a1b22
 
{
  "message": {
    "data": {
      "amount": 279.98,
      "coupon": "AUTUMN10",
      "currency": "GBP",
      "items": [
        {
          "item_brand": "NorthEdge",
          "item_category": "Jackets",
          "item_id": "SKU-1",
          "item_name": "Parka Jacket",
          "item_variant": "Blue",
          "price": 129.99,
          "quantity": 2
        },
        {
          "item_category": "Hats",
          "item_id": "SKU-2",
          "item_name": "Wool Hat",
          "price": 20,
          "quantity": 1
        }
      ],
      "order_id": "ORD-1001",
      "shipping": 4.99,
      "tax": 46.66
    },
    "template": "order_completed",
    "to": {
      "data": {
        "first_name": "Neill",
        "last_name": "Mcfixture"
      },
      "email": "neill@example.com",
      "locale": "en-GB",
      "phone_number": "+447700900123",
      "user_id": "crm-user-7"
    }
  }
}
FieldSource
message.templateThe Default Template ID when set, else the template alias named after the event.
message.to.user_idThe signed-in user ID (not the anonymous ID).
message.to.email, message.to.phone_numberFrom identify() traits; email trimmed and lower-cased, phone in E.164.
message.to.locale, message.to.dataThe visitor’s locale; first and last name.
message.dataThe event’s properties (order id, amount, currency upper-cased, items, carrier and tracking number …).
Idempotency-Key headerThe Signal event ID. Courier returns the stored response for a repeated key, so a retried delivery never sends the message twice.

Courier delivers to the email address and phone number, so they are sent in plain text; it has no hashed identifier. An event with no user ID, email or phone is dropped.

Presets

PresetSignal event → vendor event
Defaultsign_up → signed_up, purchase → order_completed, refund → order_refunded, generate_lead → lead_received
Retailsign_up → signed_up, purchase → order_completed, order_shipped, refund → order_refunded
B2B / SaaSsign_up → signed_up, trial_started, trial_expired, subscription_started, subscription_cancelled, invitation_accepted
Travelsign_up → signed_up, purchase → booking_confirmed, booking_modified, booking_cancelled

Events not listed are not sent. Each preset is a starting point: add, rename or remove mappings on the installed integration.

Notes and limits

  • Page views are not sent: every mapped event sends a notification.

Marketing-automation integrations have no consent category by default. Assign the marketing category when you install Courier, so an event is delivered only when the visitor has granted it. Cookie-banner consent is not email or SMS opt-in: keep messaging opt-in in Courier.

Verify it’s working

  1. Open the integration in the Signal Management UI and watch Live Events while you trigger a mapped event.
  2. Confirm a 2xx response from Courier.
  3. Find the contact in Courier and check the event or record arrived.

Troubleshooting

SymptomResolution
400 “template not found” or 404Create a template with the alias the event uses, or set Default Template ID.
401The API key is wrong.
402The Courier plan’s quota is used up.