Skip to content

Journey API Triggers ​

Trigger customer journeys programmatically via API endpoints. This allows you to integrate Tappd journeys with external systems, webhooks, and custom automation workflows.

Overview ​

API-triggered journeys enable:

  • External System Integration: Trigger journeys from your backend services
  • Webhook Callbacks: Trigger journeys from third-party webhooks
  • Real-time Activation: Trigger journeys immediately based on events
  • Custom Automation: Build custom workflows that trigger journeys

Prerequisites ​

  1. API Key: Get your API key from Settings > API Keys in the Tappd dashboard
  2. Active Journey: Create a journey with API trigger type in the dashboard
  3. Customer Exists: Ensure the customer exists in your workspace (identified via SDK or API)

Endpoint ​

Trigger Journey ​

Endpoint: POST /api/v1/journeys/:workspaceId/:journeyId/trigger

Base URL: https://sdk.gotappd.com/api/v1/journeys (or your custom API URL)

Authentication: API Key via Authorization header

Headers:

text
Authorization: Bearer YOUR_API_KEY
Content-Type: application/json

Request Format ​

URL Parameters ​

ParameterTypeRequiredDescription
workspaceIdStringYesYour workspace ID
journeyIdStringYesThe journey ID to trigger

Request Body ​

{
  "external_id": "user_12345",
  "payload": {
    "orderId": "ORD-12345",
    "orderTotal": 99.99,
    "productName": "Premium Plan"
  }
}

Request Body Fields ​

Single Customer (Backward Compatible) ​

FieldTypeRequiredDescription
external_id or externalIdStringYes*External customer identifier (your internal user ID)
emailStringYes*Customer email address
customerIdStringYes*Tappd customer ID (ObjectId)
payload or propertiesObjectNoCustom payload data (available in Liquid templates)

Bulk Operations (New) ​

FieldTypeRequiredDescription
external_ids or externalIdsArray[String]Yes*Array of external customer identifiers (max 1000)
segment_ids or segmentIdsArray[String]Yes*Array of segment IDs to enroll all members (max 10)
exclude_external_ids or excludeExternalIdsArray[String]NoArray of external IDs to exclude from enrollment (max 1000)
payload or propertiesObjectNoCustom payload data (available in Liquid templates)

Notes:

  • At least one identifier must be provided: external_id, email, customerId, external_ids, or segment_ids
  • If both external_ids and segment_ids are provided, only customers in both sets will be enrolled (intersection)
  • exclude_external_ids filters the final customer list regardless of source
  • Missing external_ids are silently skipped (no error)
  • Invalid segment_ids return an error

Examples ​

Example 1: Using External ID ​

bash
curl -X POST \
  'https://sdk.gotappd.com/api/v1/journeys/WORKSPACE_ID/JOURNEY_ID/trigger' \
  -H 'Authorization: Bearer YOUR_API_KEY' \
  -H 'Content-Type: application/json' \
  -d '{
    "external_id": "user_12345",
    "payload": {
      "orderId": "ORD-12345",
      "orderTotal": 99.99,
      "currency": "USD",
      "items": [
        {
          "name": "Product A",
          "quantity": 2,
          "price": 49.99
        }
      ]
    }
  }'

Example 2: Using Email ​

bash
curl -X POST \
  'https://sdk.gotappd.com/api/v1/journeys/WORKSPACE_ID/JOURNEY_ID/trigger' \
  -H 'Authorization: Bearer YOUR_API_KEY' \
  -H 'Content-Type: application/json' \
  -d '{
    "email": "[email protected]",
    "payload": {
      "eventType": "purchase_completed",
      "amount": 199.99
    }
  }'

Example 3: Using Customer ID ​

bash
curl -X POST \
  'https://sdk.gotappd.com/api/v1/journeys/WORKSPACE_ID/JOURNEY_ID/trigger' \
  -H 'Authorization: Bearer YOUR_API_KEY' \
  -H 'Content-Type: application/json' \
  -d '{
    "customerId": "507f1f77bcf86cd799439011",
    "payload": {
      "subscriptionTier": "premium",
      "upgradeDate": "2024-01-15"
    }
  }'

Example 4: JavaScript/Node.js ​

javascript
async function triggerJourney(workspaceId, journeyId, customerId, payload) {
  const response = await fetch(
    `https://sdk.gotappd.com/api/v1/journeys/${workspaceId}/${journeyId}/trigger`,
    {
      method: 'POST',
      headers: {
        'Authorization': `Bearer YOUR_API_KEY`,
        'Content-Type': 'application/json'
      },
      body: JSON.stringify({
        external_id: customerId,
        payload: payload
      })
    }
  );

  const result = await response.json();
  return result;
}

// Usage
await triggerJourney(
  'workspace_123',
  'journey_456',
  'user_789',
  {
    orderId: 'ORD-12345',
    orderTotal: 99.99
  }
);

Example 5: Python ​

python
import requests

def trigger_journey(workspace_id, journey_id, external_id, payload):
    url = f"https://sdk.gotappd.com/api/v1/journeys/{workspace_id}/{journey_id}/trigger"
    headers = {
        "Authorization": "Bearer YOUR_API_KEY",
        "Content-Type": "application/json"
    }
    data = {
        "external_id": external_id,
        "payload": payload
    }
    
    response = requests.post(url, json=data, headers=headers)
    return response.json()

# Usage
result = trigger_journey(
    "workspace_123",
    "journey_456",
    "user_789",
    {
        "orderId": "ORD-12345",
        "orderTotal": 99.99
    }
)

Example 6: Bulk Trigger with Multiple External IDs ​

bash
curl -X POST \
  'https://sdk.gotappd.com/api/v1/journeys/WORKSPACE_ID/JOURNEY_ID/trigger' \
  -H 'Authorization: Bearer YOUR_API_KEY' \
  -H 'Content-Type: application/json' \
  -d '{
    "external_ids": ["user_123", "user_456", "user_789"],
    "payload": {
      "campaign": "summer_sale",
      "discount": 20
    }
  }'

Example 7: Trigger by Segment IDs ​

bash
curl -X POST \
  'https://sdk.gotappd.com/api/v1/journeys/WORKSPACE_ID/JOURNEY_ID/trigger' \
  -H 'Authorization: Bearer YOUR_API_KEY' \
  -H 'Content-Type: application/json' \
  -d '{
    "segment_ids": ["507f1f77bcf86cd799439011", "507f1f77bcf86cd799439012"],
    "payload": {
      "event": "announcement",
      "message": "New feature available"
    }
  }'

Example 8: Intersection (External IDs + Segments) ​

bash
curl -X POST \
  'https://sdk.gotappd.com/api/v1/journeys/WORKSPACE_ID/JOURNEY_ID/trigger' \
  -H 'Authorization: Bearer YOUR_API_KEY' \
  -H 'Content-Type: application/json' \
  -d '{
    "external_ids": ["user_123", "user_456"],
    "segment_ids": ["507f1f77bcf86cd799439011"],
    "payload": {
      "campaign": "vip_promo"
    }
  }'

Note: Only customers that are in BOTH the external_ids list AND the segment_ids will be enrolled.

Example 9: With Exclusion ​

bash
curl -X POST \
  'https://sdk.gotappd.com/api/v1/journeys/WORKSPACE_ID/JOURNEY_ID/trigger' \
  -H 'Authorization: Bearer YOUR_API_KEY' \
  -H 'Content-Type: application/json' \
  -d '{
    "segment_ids": ["507f1f77bcf86cd799439011"],
    "exclude_external_ids": ["user_123", "user_456"],
    "payload": {
      "campaign": "general_announcement"
    }
  }'

Note: All customers in the segment will be enrolled, except those with external_ids in the exclusion list.

Response Format ​

Success Response (Single Customer) ​

{
  "success": true,
  "message": "Journey triggered successfully",
  "data": {
    "customerId": "507f1f77bcf86cd799439011",
    "journeyId": "507f1f77bcf86cd799439012",
    "status": "queued",
    "queued": true,
    "jobId": "enroll-507f1f77bcf86cd799439012-507f1f77bcf86cd799439011-1704067200000",
    "note": "Enrollment will be created by worker after entry rules validation"
  }
}

Success Response (Bulk Operation) ​

{
  "success": true,
  "message": "Journey triggered successfully",
  "data": {
    "journeyId": "507f1f77bcf86cd799439012",
    "status": "queued",
    "queued": true,
    "customersEnrolled": 3,
    "customerIds": [
      "507f1f77bcf86cd799439011",
      "507f1f77bcf86cd799439012",
      "507f1f77bcf86cd799439013"
    ],
    "jobIds": [
      "enroll-507f1f77bcf86cd799439012-507f1f77bcf86cd799439011-1704067200000",
      "enroll-507f1f77bcf86cd799439012-507f1f77bcf86cd799439012-1704067200001",
      "enroll-507f1f77bcf86cd799439012-507f1f77bcf86cd799439013-1704067200002"
    ],
    "note": "Enrollments will be created by worker after entry rules validation"
  }
}

Error Responses ​

Customer Not Found ​

{
  "success": false,
  "error": "Customer not found",
  "message": "Customer with external_id \"user_12345\" not found in this workspace. Please ensure the customer exists before triggering the journey."
}

Journey Not Found or Inactive ​

{
  "success": false,
  "error": "Journey not found",
  "message": "Journey not found or is not active"
}

Invalid Journey Type ​

{
  "success": false,
  "error": "Invalid journey type",
  "message": "This journey is not configured for API triggering. Current trigger type: event. Only journeys with API trigger type can be triggered via API."
}

Missing Required Parameter ​

{
  "success": false,
  "error": "Missing required parameter",
  "message": "At least one identifier is required: external_ids (array), segment_ids (array), or single external_id/email/customerId"
}

Array Size Exceeded ​

{
  "success": false,
  "error": "Array size exceeded",
  "message": "external_ids array exceeds maximum size of 1000"
}

Segment Not Found ​

{
  "success": false,
  "error": "Error resolving segments",
  "message": "One or more segments not found or do not belong to workspace: 507f1f77bcf86cd799439011"
}

Using Payload Data in Journeys ​

The payload data you send is available in Liquid templates throughout the journey.

Accessing Payload Data ​

In Liquid templates, access payload data using:

  • { { api.properties.* } } - Access payload properties
  • { { api.payload.* } } - Alternative access method

Example: Using Payload in In-App Message ​

Payload sent:

{
  "external_id": "user_123",
  "payload": {
    "orderId": "ORD-12345",
    "orderTotal": 99.99,
    "productName": "Premium Plan"
  }
}
```text

**Liquid template in message:**

Thank you for your purchase!

Order ID: { { api.properties.orderId } } Total: ${ { api.properties.orderTotal } } Product: { { api.properties.productName } }


**Rendered output:**
```text
Thank you for your purchase!

Order ID: ORD-12345
Total: $99.99
Product: Premium Plan

Example: Using Payload in Webhook ​

Webhook configuration:

{
  "url": "https://example.com/webhook",
  "method": "POST",
  "body": {
    "orderId": "{ { api.properties.orderId } }",
    "customerEmail": "{ { customer.email } }",
    "orderTotal": "{ { api.properties.orderTotal } }"
  }
}

Journey Configuration ​

Setting Up API-Triggered Journey ​

  1. Create Journey in the Tappd dashboard
  2. Set Trigger Type to "API"
  3. Configure Entry Rules (optional):
    • Maximum entries per customer
    • Re-enrollment settings
    • Entry conditions
  4. Add Steps to your journey
  5. Publish Journey

Entry Rules ​

API-triggered journeys respect entry rules:

  • Max Entries Per Customer: Limits how many times a customer can enter
  • Re-enrollment: Controls whether customers can re-enter completed journeys
  • Entry Conditions: Additional conditions that must be met

Re-enrollment Behavior ​

Multiple Entries Allowed ​

If maxEntriesPerCustomer is set (e.g., 5), and the customer has fewer completed entries:

  • The system will exit any active enrollment
  • Create a new enrollment
  • Process the new enrollment

Single Entry Only ​

If maxEntriesPerCustomer is 1 or not set:

  • If customer has an active enrollment: Returns "already enrolled"
  • If customer has a completed enrollment: Returns "already enrolled" (unless re-enrollment is enabled)

Rate Limiting ​

API journey triggers are rate-limited to prevent abuse:

  • Default Limit: 100 requests per minute per API key
  • Rate Limit Headers: Check response headers for rate limit information
  • 429 Response: Returns 429 status code when rate limit is exceeded

Best Practices ​

  1. Identify Customers First: Ensure customers are identified via SDK before triggering journeys
  2. Use External IDs: Use your internal user IDs (external_id) for consistency
  3. Include Payload Data: Send relevant data in payload for personalization
  4. Handle Errors: Implement proper error handling for API responses
  5. Monitor Journey Performance: Track journey enrollment and completion rates
  6. Test Before Production: Test journey triggers in a development environment
  7. Use Webhooks: Configure webhooks in journeys to receive notifications

Use Cases ​

E-commerce Order Confirmation ​

javascript
// Trigger journey after order completion
await triggerJourney(workspaceId, journeyId, order.customerId, {
  orderId: order.id,
  orderTotal: order.total,
  items: order.items,
  shippingAddress: order.shippingAddress
});

Subscription Upgrade ​

javascript
// Trigger journey when user upgrades subscription
await triggerJourney(workspaceId, journeyId, user.externalId, {
  subscriptionTier: 'premium',
  upgradeDate: new Date().toISOString(),
  previousTier: 'basic'
});

Event Registration ​

javascript
// Trigger journey when user registers for event
await triggerJourney(workspaceId, journeyId, user.email, {
  eventId: event.id,
  eventName: event.name,
  eventDate: event.date,
  ticketType: 'vip'
});

Webhook Integration ​

javascript
// Trigger journey from webhook
app.post('/webhook/stripe', async (req, res) => {
  const { customer, amount } = req.body;
  
  await triggerJourney(workspaceId, journeyId, customer.id, {
    paymentAmount: amount,
    paymentMethod: 'stripe',
    timestamp: new Date().toISOString()
  });
  
  res.json({ success: true });
});

Troubleshooting ​

Journey Not Triggering ​

  1. Verify Journey Status: Ensure journey is active and published
  2. Check Trigger Type: Journey must have API trigger type
  3. Verify Customer Exists: Customer must exist in workspace
  4. Check Entry Rules: Verify entry rules allow enrollment
  5. Check API Key: Verify API key has correct permissions

Customer Not Found ​

  1. Identify Customer First: Use SDK identify() method before triggering
  2. Check External ID: Verify external_id matches your system
  3. Check Workspace: Ensure customer exists in correct workspace

Payload Not Available ​

  1. Check Payload Format: Ensure payload is a valid JSON object
  2. Use Correct Template: Use { { api.properties.* } } in Liquid templates
  3. Verify Payload Keys: Check that property names match in templates

Released under the MIT License.