Mirra
Mirra APIScripts

Script Events

Event-driven scripts automatically execute when specific events occur in your Mirra account. This system enables powerful automation workflows that respond to messages, calendar events, document changes, and more.


Event System Overview

The Mirra event system allows scripts to subscribe to specific event types with optional filtering conditions. When an event matches the subscription criteria, the script executes automatically with the event data passed as the event parameter.

Event Structure

All events follow a standardized structure with common fields:

{
  "type": "telegram.message",        // Event type identifier
  "timestamp": "2025-11-15T12:00:00Z", // When the event occurred
  "actor": {                         // Who triggered the event
    "userId": "user_123",
    "name": "John Doe"
  },
  "content": {                       // Event-specific data
    "text": "Hello world"
  },
  // Integration-specific fields (e.g., telegram, gmail, etc.)
}

Creating Event Subscriptions

Endpoint

POST /api/sdk/v1/scripts/{scriptId}/subscriptions

Basic Subscription

Subscribe to all events of a specific type:

{
  "eventType": "telegram.message",
  "enabled": true
}

Filtered Subscription

Subscribe only to events matching specific conditions:

{
  "eventType": "telegram.message",
  "conditions": [
    {
      "field": "content.text",
      "operator": "contains",
      "value": "urgent"
    }
  ],
  "enabled": true
}

Condition Operators

  • equals - Exact match
  • not_equals - Not equal to value
  • contains - String contains substring
  • not_contains - String does not contain substring
  • starts_with - String starts with value
  • ends_with - String ends with value
  • greater_than - Numeric greater than
  • less_than - Numeric less than
  • exists - Field exists and is not null
  • not_exists - Field does not exist or is null

Event Handler Pattern

Basic Handler

export async function handler(event, context) {
  // Access standardized fields
  const eventType = event.type;
  const text = event.content.text;
  const sender = event.actor.name;
  const timestamp = event.timestamp;
  
  // Process the event
  console.log(`${sender} said: ${text}`);
  
  return { success: true };
}

Type-Specific Handler

export async function handler(event, context) {
  // Route based on event type
  switch (event.type) {
    case 'telegram.message':
      return handleTelegramMessage(event);
    case 'calendar.event_created':
      return handleCalendarEvent(event);
    default:
      return { success: false, error: 'Unknown event type' };
  }
}
 
function handleTelegramMessage(event) {
  const chatId = event.telegram.chatId;
  const text = event.content.text;
  // Process Telegram-specific logic
  return { success: true };
}
 
function handleCalendarEvent(event) {
  const summary = event.calendar.summary;
  const startTime = event.calendar.startTime;
  // Process calendar-specific logic
  return { success: true };
}

Available Event Types

Telegram Events

telegram.message - New message received

{
  "type": "telegram.message",
  "content": {
    "text": "Hello world"
  },
  "telegram": {
    "chatId": "123456",
    "messageId": "789",
    "isGroupChat": false
  }
}

Gmail Events

gmail.message_received - New email received

{
  "type": "gmail.message_received",
  "content": {
    "subject": "Meeting reminder",
    "body": "Don't forget about..."
  },
  "gmail": {
    "messageId": "msg_123",
    "from": "sender@example.com",
    "to": ["recipient@example.com"]
  }
}

Calendar Events

calendar.event_created - New calendar event created

{
  "type": "calendar.event_created",
  "content": {
    "summary": "Team meeting"
  },
  "calendar": {
    "eventId": "event_123",
    "startTime": "2025-11-15T14:00:00Z",
    "endTime": "2025-11-15T15:00:00Z",
    "attendees": ["user1@example.com"]
  }
}

calendar.event_updated - Calendar event modified

calendar.event_deleted - Calendar event removed

Voice Call Events

voice.call_started - Voice call initiated

voice.call_ended - Voice call completed

{
  "type": "voice.call_ended",
  "content": {
    "transcript": "Call transcript..."
  },
  "voice": {
    "callId": "call_123",
    "duration": 300,
    "participants": ["user_123", "user_456"]
  }
}

Document Events

docs.document_created - Google Doc created

docs.document_updated - Google Doc modified

drive.file_created - Google Drive file added

drive.file_updated - Google Drive file modified

sheets.spreadsheet_updated - Google Sheets modified

Crypto Events

crypto.price_alert - Price threshold crossed

{
  "type": "crypto.price_alert",
  "content": {
    "symbol": "BTC",
    "price": 50000,
    "threshold": 49000,
    "direction": "above"
  }
}

Advanced Filtering

Multiple Conditions

Combine multiple conditions (AND logic):

{
  "eventType": "telegram.message",
  "conditions": [
    {
      "field": "content.text",
      "operator": "contains",
      "value": "urgent"
    },
    {
      "field": "telegram.isGroupChat",
      "operator": "equals",
      "value": false
    }
  ]
}

Field Paths

Use dot notation to access nested fields:

{
  "field": "calendar.attendees[0]",
  "operator": "equals",
  "value": "boss@example.com"
}

Best Practices

Event Filtering

  • Filter early: Use subscription conditions instead of filtering in code
  • Be specific: Narrow subscriptions to reduce unnecessary executions
  • Test filters: Verify conditions match expected events before deployment

Error Handling

export async function handler(event, context) {
  try {
    // Validate event structure
    if (!event.content || !event.content.text) {
      throw new Error('Missing required field: content.text');
    }
    
    // Process event
    const result = await processEvent(event);
    
    return { success: true, result };
  } catch (error) {
    console.error('Event processing failed:', error);
    return { 
      success: false, 
      error: error.message,
      eventType: event.type,
      timestamp: new Date().toISOString()
    };
  }
}

Performance

  • Keep handlers fast: Event handlers should complete quickly (< 5 seconds)
  • Use async operations: Don't block on long-running tasks
  • Batch when possible: Aggregate multiple events before processing
  • Monitor execution: Track success rates and error patterns

Debugging Event Subscriptions

Test Event Delivery

Manually trigger an event subscription to test your handler:

POST /api/sdk/v1/scripts/{scriptId}/test-event
{
  "eventType": "telegram.message",
  "eventData": {
    "type": "telegram.message",
    "content": {
      "text": "Test message"
    }
  }
}

View Subscription Logs

Check execution history for event-triggered runs:

GET /api/sdk/v1/scripts/{scriptId}/executions?trigger=event

See Also

On this page