Skip to main content

Overview

API-triggered campaigns let you configure message templates and targeting rules in the Clix console, then trigger delivery from your backend via API. This approach separates campaign logic from your application code, making it easier for non-technical team members to manage messaging while developers maintain simple API calls. See Campaign Types for a comparison with scheduled and event-triggered campaigns.

When to Use

API-triggered campaigns work well when you need:
  • Transactional notifications: Order confirmations, password resets, payment alerts
  • Workflow notifications: Task assignments, approval requests, status updates
  • System alerts: Moderation queues, support tickets, server events
  • Programmatic sends: Any scenario where your backend knows when to send but non-technical users should control the content and targeting

Example Scenario

Your retail app allows customers to place online orders for pickup at different store locations. When a new order is placed, you want to notify staff at that specific store. Without API-triggered campaigns, you’d need to:
  1. Query your database for staff members at the store location
  2. Build the notification payload with order details
  3. Call a send API for each recipient
With API-triggered campaigns:
  1. Configure a campaign once in the console with targeting rules and message template
  2. Call the trigger endpoint with just the store location and order details
  3. Clix handles filtering, personalization, and delivery

Setting Up a Campaign

1. Create the Campaign

In the Clix console:
  1. Go to Campaigns > Create Campaign
  2. Choose your message channel and configure the content
  3. In the Schedule & Launch step, select API-Triggered
See Campaigns Quickstart for detailed campaign creation steps.

2. Configure Dynamic Audience Filters

API-triggered campaigns support dynamic audience filtering, where filter values come from your API request instead of being hardcoded. Use the trigger.* namespace in your audience conditions to reference API payload data:
Group 1
  user_role equals "store_staff"
  AND
  store_location equals {{ trigger.store_location }}
When you call the API with "store_location": "San Francisco", Clix will only send to users where:
  • user_role equals "store_staff" (static condition)
  • store_location equals "San Francisco" (dynamic condition from API payload)

Supported Operators

For dynamic filters, you can use:
  • Equals (==)
  • Not equals (!=)
  • Exists
  • Not exists
  • In
  • Not in

Filter Limitations

To ensure performance when filtering on-demand:
  • Maximum 3 attributes per audience definition
  • Attributes can be combined with AND or OR operators
  • Groups are supported within these constraints
Complex targeting logic should be handled in your backend before calling the trigger API.

3. Add Dynamic Content

Use Personalization syntax to insert dynamic values in your message content. The trigger.* namespace contains properties from your API request: Message title:
New order at {{ trigger.store_name }}
Message body:
Order #{{ trigger.order_id }} from {{ trigger.customer_name }}
{{ trigger.item_count }} items - Ready by {{ trigger.pickup_time }}
Deep link:
myapp://orders/{{ trigger.order_id }}
See the Personalization guide for filters, conditionals, and loops.

4. Save and Get Campaign ID

After saving your campaign, you’ll see:
  • Campaign ID: Use this to trigger the campaign via API
  • Sample API request: Example code snippets
You can also find the campaign ID later:
  1. Go to Campaigns
  2. Click on your campaign
  3. The campaign ID appears in the URL: console.clix.so/campaigns/{campaign_id}
Or view it in the campaign details panel.

Triggering from Your Backend

Call the trigger endpoint when you want to send the campaign:
POST https://api.clix.so/api/v1/campaigns/{campaign_id}:trigger
X-Clix-Project-ID: your_project_id
X-Clix-API-Key: your_api_key
Content-Type: application/json

{
  "audience": {
    "broadcast": true
  },
  "properties": {
    "store_name": "Downtown Store",
    "store_location": "San Francisco",
    "customer_name": "Sarah Johnson",
    "order_id": "ORD-12345",
    "item_count": "3",
    "pickup_time": "2:30 PM"
  }
}
The properties object contains data for both:
  • Audience filtering: Values referenced in {{ trigger.* }} conditions
  • Message personalization: Values inserted in message templates
See the Trigger Campaign API Reference for all options including targeting specific users.

Full Example

Let’s build an order notification system for retail stores.

Console Configuration

Campaign name: New Order Alerts Audience:
Group 1
  user_role equals "store_staff"
  AND
  store_location equals {{ trigger.store_location }}
Message:
  • Title: New pickup order
  • Body: Order #{{ trigger.order_id }} from {{ trigger.customer_name }}. {{ trigger.item_count }} items ready by {{ trigger.pickup_time }}.
  • Deep link: myapp://orders/{{ trigger.order_id }}
Campaign ID: 019aa002-1d0e-7407-a0c5-5bfa8dd2be30

Backend Implementation

When a customer places an order:
async function notifyStoreStaff(order) {
  const response = await fetch(
    'https://api.clix.so/api/v1/campaigns/019aa002-1d0e-7407-a0c5-5bfa8dd2be30:trigger',
    {
      method: 'POST',
      headers: {
        'X-Clix-Project-ID': process.env.CLIX_PROJECT_ID,
        'X-Clix-API-Key': process.env.CLIX_API_KEY,
        'Content-Type': 'application/json'
      },
      body: JSON.stringify({
        audience: {
          broadcast: true
        },
        properties: {
          store_location: order.pickupLocation,
          customer_name: order.customer.name,
          order_id: order.id,
          item_count: order.items.length,
          pickup_time: order.pickupTime
        }
      })
    }
  );

  return response.json();
}

Result

For an order placed at the San Francisco store:
  • Clix filters audience to staff where store_location == "San Francisco"
  • Each staff member receives a notification with the order details
  • Title: “New pickup order”
  • Body: “Order #ORD-12345 from Sarah Johnson. 3 items ready by 2:30 PM.”
To notify staff at the New York store, call the same endpoint with "store_location": "New York". No new campaign needed.

Best Practices

  • Keep filter logic simple: Use 3 or fewer attributes. Move complex logic to your backend.
  • Pre-format data: Send "$29.99" instead of 2999 if you want to display formatted prices.
  • Use meaningful property names: facility_name is clearer than fn or name1.
  • Test with sample data: Use the campaign preview feature to verify personalization before going live.
  • Handle missing data: Use the default filter for optional properties: {{ trigger.discount | default: "10%" }}

Limitations

  • Audience attributes: Maximum 3 attributes in filter conditions
  • Filter operators: Limited to equals, not equals, exists, not exists, in, not in
  • Campaign edits: Changing audience or message requires creating a new campaign or updating the existing one (campaign ID remains the same)
  • Rate limits: See API Rate Limits for request quotas
For more flexible targeting without these constraints, consider Event-Triggered Campaigns if your use case fits an event-based model.