Triggers API

Triggers enable automatic responses and actions based on user input patterns. They provide a powerful way to handle common user requests without requiring AI processing, improving response time and consistency.

Overview

Triggers work in two phases:

  1. Keyword Triggers — Matched before AI processing (instant response)
  2. Intent Triggers — Matched after AI processing (requires AI to detect intent)
User: "show me pricing"
         ↓
   ┌─────────────────────┐
   │  Keyword Matching   │ ← Phase 1: Check for "pricing" keyword
   └─────────────────────┘
         ↓ (no match or skipAgent: false)
   ┌─────────────────────┐
   │   AI Processing     │ ← AI generates response, extracts intent
   └─────────────────────┘
         ↓
   ┌─────────────────────┐
   │  Intent Matching    │ ← Phase 2: Check for detected intent
   └─────────────────────┘
         ↓
   Response with actions/content

Trigger Object

interface Trigger {
  id: string;
  type: 'keyword' | 'intent';

  trigger: {
    value: string;        // Keyword pattern or intent name
    confidence?: number;  // For intents: minimum confidence (0-1)
    examples?: string[];  // For intents: training examples
  };

  response?: {
    contentId?: string;   // Return specific content
    message?: string;     // Return direct message
  };

  actions?: ClientAction[];

  options?: {
    skipAgent?: boolean;    // Skip AI entirely (keyword triggers)
    actionsOnly?: boolean;  // Only return actions, no content
    priority?: number;      // Higher = checked first
  };

  enabled: boolean;
  tags?: string[];
  createdAt: string;
  updatedAt: string;
}

Keyword Patterns

Keyword triggers support several matching patterns:

| Pattern | Example | Matches | |---------|---------|---------| | Simple | "pricing" | Input contains "pricing" | | Exact | "[pricing]" | Input is exactly "pricing" | | AND | "red+wine" | Input contains both "red" AND "wine" | | Multiple | "hi,hello,hey" | Input contains any: "hi", "hello", or "hey" |

Examples

// Simple match - matches "show me pricing" or "pricing info"
{ type: 'keyword', trigger: { value: 'pricing' } }

// Exact match - only matches exactly "help"
{ type: 'keyword', trigger: { value: '[help]' } }

// AND match - "I want a red wine" matches
{ type: 'keyword', trigger: { value: 'red+wine' } }

// Multiple - any greeting matches
{ type: 'keyword', trigger: { value: 'hi,hello,hey,howdy' } }

API Endpoints

List Triggers

GET /api/sdk/triggers

Query Parameters:

| Parameter | Type | Description | |-----------|------|-------------| | type | keyword \| intent | Filter by trigger type | | enabled | true \| false | Filter by status | | tag | string | Filter by tag | | limit | number | Results per page (default: 50, max: 100) | | offset | number | Pagination offset |

Response:

{
  "success": true,
  "data": {
    "triggers": [
      {
        "id": "trigger_abc123",
        "type": "keyword",
        "trigger": {
          "value": "pricing",
          "confidence": 0.7,
          "examples": []
        },
        "response": {
          "message": "Our pricing starts at $29/month. Check out fig1.ai/pricing for details!"
        },
        "actions": [
          {
            "type": "navigate",
            "payload": { "route": "/pricing" },
            "priority": 1
          }
        ],
        "options": {
          "skipAgent": true,
          "actionsOnly": false,
          "priority": 10
        },
        "enabled": true,
        "tags": ["navigation"],
        "createdAt": "2024-12-21T10:00:00Z",
        "updatedAt": "2024-12-21T10:00:00Z"
      }
    ],
    "pagination": {
      "total": 15,
      "limit": 50,
      "offset": 0,
      "hasMore": false
    }
  }
}

Example:

curl -X GET "https://app.fig1.ai/api/sdk/triggers?type=keyword&enabled=true" \
  -H "X-Fig1-API-Key: fig1_sdk_your_api_key"

Create Trigger

POST /api/sdk/triggers

Request Body:

{
  type: 'keyword' | 'intent';  // Required

  trigger: {
    value: string;             // Required: keyword pattern or intent name
    confidence?: number;       // Optional: 0-1 (default: 0.7)
    examples?: string[];       // Optional: training examples for intents
  };

  response?: {
    contentId?: string;        // Optional: content composition ID
    message?: string;          // Optional: direct message response
  };

  actions?: Array<{
    type: string;
    payload: object;
    priority?: number;
    label?: string;
  }>;

  options?: {
    skipAgent?: boolean;       // Default: false
    actionsOnly?: boolean;     // Default: false
    priority?: number;         // Default: 0
  };

  enabled?: boolean;           // Default: true
  tags?: string[];
}

Response:

{
  "success": true,
  "data": {
    "id": "trigger_new123",
    "type": "keyword",
    "trigger": { "value": "pricing", "confidence": 0.7, "examples": [] },
    "response": { "message": "Check out our pricing page!" },
    "actions": [],
    "options": { "skipAgent": true, "actionsOnly": false, "priority": 0 },
    "enabled": true,
    "tags": [],
    "createdAt": "2024-12-21T10:00:00Z",
    "updatedAt": "2024-12-21T10:00:00Z"
  }
}

Examples:

Keyword trigger with navigation action

curl -X POST https://app.fig1.ai/api/sdk/triggers \
  -H "Content-Type: application/json" \
  -H "X-Fig1-API-Key: fig1_sdk_your_api_key" \
  -d '{
    "type": "keyword",
    "trigger": { "value": "pricing,prices,cost" },
    "response": { "message": "Let me take you to our pricing page!" },
    "actions": [
      {
        "type": "navigate",
        "payload": { "route": "/pricing" },
        "priority": 1
      }
    ],
    "options": { "skipAgent": true },
    "tags": ["navigation"]
  }'

Intent trigger for booking

curl -X POST https://app.fig1.ai/api/sdk/triggers \
  -H "Content-Type: application/json" \
  -H "X-Fig1-API-Key: fig1_sdk_your_api_key" \
  -d '{
    "type": "intent",
    "trigger": {
      "value": "book_appointment",
      "confidence": 0.8,
      "examples": [
        "I want to book an appointment",
        "Can I schedule a meeting?",
        "Book a time slot",
        "I need to make a reservation"
      ]
    },
    "actions": [
      {
        "type": "open_modal",
        "payload": { "modalId": "booking-calendar" }
      }
    ],
    "tags": ["booking"]
  }'

Actions-only trigger (no message)

curl -X POST https://app.fig1.ai/api/sdk/triggers \
  -H "Content-Type: application/json" \
  -H "X-Fig1-API-Key: fig1_sdk_your_api_key" \
  -d '{
    "type": "keyword",
    "trigger": { "value": "dark mode,night mode" },
    "actions": [
      {
        "type": "trigger_event",
        "payload": { "eventName": "theme:toggle", "eventData": { "theme": "dark" } }
      }
    ],
    "options": { "skipAgent": true, "actionsOnly": true }
  }'

Get Trigger

GET /api/sdk/triggers/:id

Response:

{
  "success": true,
  "data": {
    "id": "trigger_abc123",
    "type": "keyword",
    "trigger": { "value": "pricing", "confidence": 0.7, "examples": [] },
    "response": { "message": "Check out our pricing page!" },
    "actions": [],
    "options": { "skipAgent": true, "actionsOnly": false, "priority": 0 },
    "enabled": true,
    "tags": ["navigation"],
    "createdAt": "2024-12-21T10:00:00Z",
    "updatedAt": "2024-12-21T10:00:00Z"
  }
}

Update Trigger

PUT /api/sdk/triggers/:id

Request Body (all fields optional):

{
  trigger?: {
    value?: string;
    confidence?: number;
    examples?: string[];
  };
  response?: {
    contentId?: string;
    message?: string;
  };
  actions?: ClientAction[];
  options?: {
    skipAgent?: boolean;
    actionsOnly?: boolean;
    priority?: number;
  };
  enabled?: boolean;
  tags?: string[];
}

Example:

curl -X PUT https://app.fig1.ai/api/sdk/triggers/trigger_abc123 \
  -H "Content-Type: application/json" \
  -H "X-Fig1-API-Key: fig1_sdk_your_api_key" \
  -d '{
    "enabled": false,
    "options": { "priority": 20 }
  }'

Delete Trigger

DELETE /api/sdk/triggers/:id

Response:

{
  "success": true,
  "data": {
    "id": "trigger_abc123",
    "deleted": true
  }
}

Action Types

Triggers can include any of these action types:

| Type | Description | Payload Fields | |------|-------------|----------------| | navigate | Navigate to app route | route, params | | open_url | Open external URL | url | | open_content | Display content | contentId | | play_video | Play video | videoId, timestamp | | show_product | Show product details | productId | | add_to_cart | Add to cart | productId, quantity | | open_modal | Open modal/dialog | modalId, modalData | | trigger_event | Fire custom event | eventName, eventData | | custom | App-specific action | customType, customData |

See Client Actions for detailed handling instructions.


Chat Response Integration

When a trigger matches during chat, the response includes trigger information:

{
  "success": true,
  "data": {
    "message": "Let me take you to our pricing page!",
    "sessionId": "sess_abc123",
    "actions": [
      {
        "type": "navigate",
        "payload": { "route": "/pricing" },
        "priority": 1
      }
    ],
    "triggeredBy": {
      "type": "keyword",
      "value": "pricing"
    },
    "metadata": {
      "model": "keyword-trigger",
      "tokensUsed": 0,
      "proxyLatencyMs": 15,
      "triggerPhase": "pre-agent"
    }
  }
}

Key Fields

| Field | Description | |-------|-------------| | triggeredBy.type | "keyword" or "intent" | | triggeredBy.value | The matched keyword or intent name | | metadata.triggerPhase | "pre-agent" (keyword) or "post-agent" (intent) | | metadata.tokensUsed | 0 for keyword triggers (no AI used) |


Best Practices

1. Use Keywords for Navigation

Keyword triggers skip AI processing entirely, making them ideal for common navigation requests:

// Fast: Instant response, no AI cost
{
  type: 'keyword',
  trigger: { value: 'contact,support,help' },
  response: { message: 'Here\'s our contact page!' },
  actions: [{ type: 'navigate', payload: { route: '/contact' } }],
  options: { skipAgent: true }
}

2. Use Intents for Complex Requests

Intent triggers leverage AI understanding for nuanced requests:

// Flexible: AI understands variations
{
  type: 'intent',
  trigger: {
    value: 'request_refund',
    confidence: 0.75,
    examples: [
      'I want my money back',
      'This isn\'t what I ordered',
      'Can I return this?'
    ]
  },
  actions: [{ type: 'open_modal', payload: { modalId: 'refund-form' } }]
}

3. Set Appropriate Confidence Thresholds

| Confidence | Use Case | |------------|----------| | 0.9+ | Critical actions (payments, cancellations) | | 0.7-0.9 | Standard actions (navigation, modals) | | 0.5-0.7 | Suggestions (non-critical) |

4. Use Priority for Ordering

Higher priority triggers are checked first:

// Priority 100: Emergency/safety keywords checked first
{ trigger: { value: 'emergency' }, options: { priority: 100 } }

// Priority 50: Important navigation
{ trigger: { value: 'pricing' }, options: { priority: 50 } }

// Priority 0: General triggers (default)
{ trigger: { value: 'hello' }, options: { priority: 0 } }

5. Combine Actions and Messages

Triggers can include both a response message and actions:

{
  type: 'keyword',
  trigger: { value: 'book' },
  response: { message: 'Opening our booking calendar for you!' },
  actions: [
    { type: 'open_modal', payload: { modalId: 'booking' } },
    { type: 'trigger_event', payload: { eventName: 'booking:started' } }
  ],
  options: { skipAgent: true }
}

Error Responses

Invalid Trigger ID (400)

{
  "success": false,
  "error": "Invalid trigger ID"
}

Trigger Not Found (404)

{
  "success": false,
  "error": "Trigger not found"
}

Duplicate Trigger (409)

{
  "success": false,
  "error": "A keyword trigger with this value already exists"
}

Invalid Type (400)

{
  "success": false,
  "error": "type must be \"keyword\" or \"intent\""
}

Missing Value (400)

{
  "success": false,
  "error": "trigger.value is required"
}