Signal System

Event API

The Event API provides programmatic access to Compozy's signal system, enabling external applications, services, and integrations to participate in event-driven workflows. This RESTful API is essential for building complex integrations, webhook handlers, and distributed system coordination with Compozy workflows.

API Implementation Status

Compozy's signal system is production-ready and fully operational, providing robust workflow-to-workflow communication. The Event API offers multiple endpoints for different integration patterns, from direct workflow signaling to event-driven triggers.

Signal to Workflow Execution

Send signals to running workflows via POST /api/v0/executions/workflows/:exec_id/signals

Event Endpoint (Experimental)

Trigger workflows with events via POST /api/v0/events

Architecture

Compozy's Event API integrates seamlessly with the signal system architecture through multiple coordination patterns:

Internal Signaling

Workflow-to-workflow communication via signal tasks

External Integration

API-driven signals from external systems and services

Hybrid Coordination

Mixed internal/external signal patterns for complex scenarios

Signal Publication

Signal tasks and Event API endpoints dispatch structured signals

Signal Reception

Wait tasks and signal triggers receive and process signals

Workflow Orchestration

Signals coordinate workflow execution, trigger new workflows, and enable complex patterns

Endpoints

Signal to Workflow Execution

Send signals to running workflow executions:

POST /api/v0/executions/workflows/{exec_id}/signals
Content-Type: application/json
Authorization: Bearer YOUR_API_KEY

{
  "signal_name": "user-approved",
  "payload": {
    "user_id": "123",
    "approval_status": "approved",
    "approved_by": "manager@company.com"
  }
}

Event Endpoint

Trigger workflows using events:

POST /api/v0/events
Content-Type: application/json

{
  "name": "workflow.trigger",
  "payload": {
    "user_id": "123",
    "request_type": "approval"
  }
}

Authentication

When authentication is enabled, all API requests require proper credentials:

# Using API key authentication
curl -X POST http://localhost:8080/api/v0/executions/workflows/{exec_id}/signals \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "signal_name": "approval-decision",
    "payload": {"status": "approved"}
  }'

Integration Examples

External Approval System

Integrate Compozy with your existing approval systems:

const axios = require('axios');

class ApprovalIntegration {
  constructor(compozyUrl, apiKey) {
    this.client = axios.create({
      baseURL: compozyUrl,
      headers: {
        'Authorization': `Bearer ${apiKey}`,
        'Content-Type': 'application/json'
      }
    });
  }

  async sendApprovalDecision(workflowExecId, decision) {
    try {
      const response = await this.client.post(
        `/api/v0/executions/workflows/${workflowExecId}/signals`,
        {
          signal_name: 'approval-decision',
          payload: {
            decision: decision,
            approved_by: 'external-system',
            timestamp: new Date().toISOString()
          }
        }
      );
      return response.data;
    } catch (error) {
      console.error('Failed to send approval signal:', error);
      throw error;
    }
  }
}

// Usage
const approval = new ApprovalIntegration('http://localhost:8080', 'your-api-key');
await approval.sendApprovalDecision('exec_123', 'approved');

Payment Gateway Integration

Handle payment webhooks and notify workflows:

// Express.js webhook handler for payment gateway
const express = require('express');
const app = express();
app.use(express.json());

app.post('/webhooks/payment', async (req, res) => {
  const { event_type, transaction_id, workflow_exec_id, amount, status } = req.body;

  try {
    // Send payment status to waiting workflow
    if (workflow_exec_id) {
      await axios.post(
        `http://localhost:8080/api/v0/executions/workflows/${workflow_exec_id}/signals`,
        {
          signal_name: 'payment-status',
          payload: {
            transaction_id,
            status,
            amount,
            event_type,
            processed_at: new Date().toISOString()
          }
        },
        {
          headers: {
            'Authorization': 'Bearer YOUR_API_KEY',
            'Content-Type': 'application/json'
          }
        }
      );
    }

    res.json({ success: true });
  } catch (error) {
    console.error('Failed to process payment webhook:', error);
    res.status(500).json({ error: 'Processing failed' });
  }
});

Working with Workflow YAML

When building workflows that integrate with external systems, use signal tasks and wait tasks:

# Workflow that processes external approvals
workflows:
  - id: approval-processor
    triggers:
      - type: signal
        name: approval-request

    tasks:
      - id: wait-for-decision
        type: wait
        wait_for: approval-decision
        on_timeout: handle-timeout

      - id: process-approval
        type: basic
        agent: processor-agent
        prompt: |
          Process the approval decision:
          Decision: {{ .tasks.wait_for_decision.result.payload.decision }}
          Approved by: {{ .tasks.wait_for_decision.result.payload.approved_by }}

Best Practices

Use Consistent Signal Naming

Adopt a naming convention like `domain-action` (e.g., `user-approved`, `payment-completed`) for maintainable signal systems.

Structure Payloads Thoughtfully

Include essential data in signal payloads while keeping them lightweight. Use consistent field names across similar signals.

Implement Retry Logic

Add retry mechanisms with exponential backoff for transient failures, especially for critical signals.

Monitor Signal Activity

Track signal delivery and processing to ensure reliable workflow execution.

Next Steps