Sim

API externa

Sim proporciona una API externa completa para consultar registros de ejecución de flujos de trabajo y configurar webhooks para notificaciones en tiempo real cuando los flujos de trabajo se completan.

Autenticación

Todas las solicitudes a la API requieren una clave de API pasada en el encabezado x-api-key:

curl -H "x-api-key: YOUR_API_KEY" \
  https://sim.ai/api/v1/logs?workspaceId=YOUR_WORKSPACE_ID

Puedes generar claves de API desde la configuración de usuario en el panel de control de Sim.

API de registros

Todas las respuestas de la API incluyen información sobre tus límites de ejecución de flujos de trabajo y su uso:

"limits": {
  "workflowExecutionRateLimit": {
    "sync": {
      "requestsPerMinute": 60,  // Sustained rate limit per minute
      "maxBurst": 120,          // Maximum burst capacity
      "remaining": 118,         // Current tokens available (up to maxBurst)
      "resetAt": "..."          // When tokens next refill
    },
    "async": {
      "requestsPerMinute": 200, // Sustained rate limit per minute
      "maxBurst": 400,          // Maximum burst capacity
      "remaining": 398,         // Current tokens available
      "resetAt": "..."          // When tokens next refill
    }
  },
  "usage": {
    "currentPeriodCost": 1.234,  // Current billing period usage in USD
    "limit": 10,                  // Usage limit in USD
    "plan": "pro",                // Current subscription plan
    "isExceeded": false           // Whether limit is exceeded
  }
}

Nota: Los límites de tasa utilizan un algoritmo de cubo de tokens. remaining puede exceder requestsPerMinute hasta maxBurst cuando no has usado tu asignación completa recientemente, permitiendo tráfico en ráfagas. Los límites de tasa en el cuerpo de la respuesta son para ejecuciones de flujo de trabajo. Los límites de tasa para llamar a este punto final de la API están en los encabezados de respuesta (X-RateLimit-*).

Consultar registros

Consulta los registros de ejecución de flujos de trabajo con amplias opciones de filtrado.

GET /api/v1/logs

Parámetros requeridos:

  • workspaceId - Tu ID de espacio de trabajo

Filtros opcionales:

  • workflowIds - IDs de flujos de trabajo separados por comas
  • folderIds - IDs de carpetas separados por comas
  • triggers - Tipos de disparadores separados por comas: api, webhook, schedule, manual, chat
  • level - Filtrar por nivel: info, error
  • startDate - Marca de tiempo ISO para el inicio del rango de fechas
  • endDate - Marca de tiempo ISO para el fin del rango de fechas
  • executionId - Coincidencia exacta de ID de ejecución
  • minDurationMs - Duración mínima de ejecución en milisegundos
  • maxDurationMs - Duración máxima de ejecución en milisegundos
  • minCost - Costo mínimo de ejecución
  • maxCost - Costo máximo de ejecución
  • model - Filtrar por modelo de IA utilizado

Paginación:

  • limit - Resultados por página (predeterminado: 100)
  • cursor - Cursor para la siguiente página
  • order - Orden de clasificación: desc, asc (predeterminado: desc)

Nivel de detalle:

  • details - Nivel de detalle de la respuesta: basic, full (predeterminado: básico)
  • includeTraceSpans - Incluir intervalos de seguimiento (predeterminado: falso)
  • includeFinalOutput - Incluir salida final (predeterminado: falso)
{
  "data": [
    {
      "id": "log_abc123",
      "workflowId": "wf_xyz789",
      "executionId": "exec_def456",
      "level": "info",
      "trigger": "api",
      "startedAt": "2025-01-01T12:34:56.789Z",
      "endedAt": "2025-01-01T12:34:57.123Z",
      "totalDurationMs": 334,
      "cost": {
        "total": 0.00234
      },
      "files": null
    }
  ],
  "nextCursor": "eyJzIjoiMjAyNS0wMS0wMVQxMjozNDo1Ni43ODlaIiwiaWQiOiJsb2dfYWJjMTIzIn0",
  "limits": {
    "workflowExecutionRateLimit": {
      "sync": {
        "requestsPerMinute": 60,
        "maxBurst": 120,
        "remaining": 118,
        "resetAt": "2025-01-01T12:35:56.789Z"
      },
      "async": {
        "requestsPerMinute": 200,
        "maxBurst": 400,
        "remaining": 398,
        "resetAt": "2025-01-01T12:35:56.789Z"
      }
    },
    "usage": {
      "currentPeriodCost": 1.234,
      "limit": 10,
      "plan": "pro",
      "isExceeded": false
    }
  }
}

Obtener detalles del registro

Recupera información detallada sobre una entrada de registro específica.

GET /api/v1/logs/{id}
{
  "data": {
    "id": "log_abc123",
    "workflowId": "wf_xyz789",
    "executionId": "exec_def456",
    "level": "info",
    "trigger": "api",
    "startedAt": "2025-01-01T12:34:56.789Z",
    "endedAt": "2025-01-01T12:34:57.123Z",
    "totalDurationMs": 334,
    "workflow": {
      "id": "wf_xyz789",
      "name": "My Workflow",
      "description": "Process customer data"
    },
    "executionData": {
      "traceSpans": [...],
      "finalOutput": {...}
    },
    "cost": {
      "total": 0.00234,
      "tokens": {
        "prompt": 123,
        "completion": 456,
        "total": 579
      },
      "models": {
        "gpt-4o": {
          "input": 0.001,
          "output": 0.00134,
          "total": 0.00234,
          "tokens": {
            "prompt": 123,
            "completion": 456,
            "total": 579
          }
        }
      }
    },
    "limits": {
      "workflowExecutionRateLimit": {
        "sync": {
          "requestsPerMinute": 60,
          "maxBurst": 120,
          "remaining": 118,
          "resetAt": "2025-01-01T12:35:56.789Z"
        },
        "async": {
          "requestsPerMinute": 200,
          "maxBurst": 400,
          "remaining": 398,
          "resetAt": "2025-01-01T12:35:56.789Z"
        }
      },
      "usage": {
        "currentPeriodCost": 1.234,
        "limit": 10,
        "plan": "pro",
        "isExceeded": false
      }
    }
  }
}

Obtener detalles de ejecución

Recupera detalles de ejecución incluyendo la instantánea del estado del flujo de trabajo.

GET /api/v1/logs/executions/{executionId}
{
  "executionId": "exec_def456",
  "workflowId": "wf_xyz789",
  "workflowState": {
    "blocks": {...},
    "edges": [...],
    "loops": {...},
    "parallels": {...}
  },
  "executionMetadata": {
    "trigger": "api",
    "startedAt": "2025-01-01T12:34:56.789Z",
    "endedAt": "2025-01-01T12:34:57.123Z",
    "totalDurationMs": 334,
    "cost": {...}
  }
}

Notificaciones

Recibe notificaciones en tiempo real cuando se completan las ejecuciones de flujos de trabajo a través de webhook, correo electrónico o Slack. Las notificaciones se configuran a nivel de espacio de trabajo desde la página de Registros.

Configuración

Configura las notificaciones desde la página de Registros haciendo clic en el botón de menú y seleccionando "Configurar notificaciones".

Canales de notificación:

  • Webhook: Envía solicitudes HTTP POST a tu punto de conexión
  • Correo electrónico: Recibe notificaciones por correo con detalles de la ejecución
  • Slack: Publica mensajes en un canal de Slack

Selección de flujos de trabajo:

  • Selecciona flujos de trabajo específicos para monitorear
  • O elige "Todos los flujos de trabajo" para incluir los flujos actuales y futuros

Opciones de filtrado:

  • levelFilter: Niveles de registro a recibir (info, error)
  • triggerFilter: Tipos de disparadores a recibir (api, webhook, schedule, manual, chat)

Datos opcionales:

  • includeFinalOutput: Incluir la salida final del flujo de trabajo
  • includeTraceSpans: Incluir trazas detalladas de la ejecución
  • includeRateLimits: Incluir información de límites de tasa (límites sincrónicos/asincrónicos y restantes)
  • includeUsageData: Incluir uso y límites del período de facturación

Reglas de alerta

En lugar de recibir notificaciones por cada ejecución, configura reglas de alerta para ser notificado solo cuando se detecten problemas:

Fallos consecutivos

  • Alerta después de X ejecuciones fallidas consecutivas (por ejemplo, 3 fallos seguidos)
  • Se reinicia cuando una ejecución tiene éxito

Tasa de fallos

  • Alerta cuando la tasa de fallos supera el X% durante las últimas Y horas
  • Requiere un mínimo de 5 ejecuciones en la ventana de tiempo
  • Solo se activa después de que haya transcurrido la ventana de tiempo completa

Umbral de latencia

  • Alerta cuando cualquier ejecución tarda más de X segundos
  • Útil para detectar flujos de trabajo lentos o bloqueados

Pico de latencia

  • Alerta cuando la ejecución es X% más lenta que el promedio
  • Compara con la duración promedio durante la ventana de tiempo configurada
  • Requiere un mínimo de 5 ejecuciones para establecer una línea base

Umbral de costo

  • Alerta cuando una sola ejecución cuesta más de $X
  • Útil para detectar llamadas costosas a LLM

Sin actividad

  • Alerta cuando no ocurren ejecuciones dentro de X horas
  • Útil para monitorear flujos de trabajo programados que deberían ejecutarse regularmente

Recuento de errores

  • Alerta cuando el recuento de errores excede X dentro de una ventana de tiempo
  • Rastrea errores totales, no consecutivos

Todos los tipos de alertas incluyen un período de enfriamiento de 1 hora para evitar el spam de notificaciones.

Configuración de webhook

Para webhooks, hay opciones adicionales disponibles:

  • url: La URL de tu endpoint webhook
  • secret: Secreto opcional para verificación de firma HMAC

Estructura de carga útil

Cuando se completa la ejecución de un flujo de trabajo, Sim envía la siguiente carga útil (vía webhook POST, correo electrónico o Slack):

{
  "id": "evt_123",
  "type": "workflow.execution.completed",
  "timestamp": 1735925767890,
  "data": {
    "workflowId": "wf_xyz789",
    "executionId": "exec_def456",
    "status": "success",
    "level": "info",
    "trigger": "api",
    "startedAt": "2025-01-01T12:34:56.789Z",
    "endedAt": "2025-01-01T12:34:57.123Z",
    "totalDurationMs": 334,
    "cost": {
      "total": 0.00234,
      "tokens": {
        "prompt": 123,
        "completion": 456,
        "total": 579
      },
      "models": {
        "gpt-4o": {
          "input": 0.001,
          "output": 0.00134,
          "total": 0.00234,
          "tokens": {
            "prompt": 123,
            "completion": 456,
            "total": 579
          }
        }
      }
    },
    "files": null,
    "finalOutput": {...},  // Only if includeFinalOutput=true
    "traceSpans": [...],   // Only if includeTraceSpans=true
    "rateLimits": {...},   // Only if includeRateLimits=true
    "usage": {...}         // Only if includeUsageData=true
  },
  "links": {
    "log": "/v1/logs/log_abc123",
    "execution": "/v1/logs/executions/exec_def456"
  }
}

Encabezados de webhook

Cada solicitud de webhook incluye estos encabezados (solo canal webhook):

  • sim-event: Tipo de evento (siempre workflow.execution.completed)
  • sim-timestamp: Marca de tiempo Unix en milisegundos
  • sim-delivery-id: ID único de entrega para idempotencia
  • sim-signature: Firma HMAC-SHA256 para verificación (si se configura un secreto)
  • Idempotency-Key: Igual que el ID de entrega para detección de duplicados

Verificación de firma

Si configuras un secreto de webhook, verifica la firma para asegurar que el webhook proviene de Sim:

import crypto from 'crypto';

function verifyWebhookSignature(body, signature, secret) {
  const [timestampPart, signaturePart] = signature.split(',');
  const timestamp = timestampPart.replace('t=', '');
  const expectedSignature = signaturePart.replace('v1=', '');
  
  const signatureBase = `${timestamp}.${body}`;
  const hmac = crypto.createHmac('sha256', secret);
  hmac.update(signatureBase);
  const computedSignature = hmac.digest('hex');
  
  return computedSignature === expectedSignature;
}

// In your webhook handler
app.post('/webhook', (req, res) => {
  const signature = req.headers['sim-signature'];
  const body = JSON.stringify(req.body);
  
  if (!verifyWebhookSignature(body, signature, process.env.WEBHOOK_SECRET)) {
    return res.status(401).send('Invalid signature');
  }
  
  // Process the webhook...
});
import hmac
import hashlib
import json

def verify_webhook_signature(body: str, signature: str, secret: str) -> bool:
    timestamp_part, signature_part = signature.split(',')
    timestamp = timestamp_part.replace('t=', '')
    expected_signature = signature_part.replace('v1=', '')
    
    signature_base = f"{timestamp}.{body}"
    computed_signature = hmac.new(
        secret.encode(),
        signature_base.encode(),
        hashlib.sha256
    ).hexdigest()
    
    return hmac.compare_digest(computed_signature, expected_signature)

# In your webhook handler
@app.route('/webhook', methods=['POST'])
def webhook():
    signature = request.headers.get('sim-signature')
    body = json.dumps(request.json)
    
    if not verify_webhook_signature(body, signature, os.environ['WEBHOOK_SECRET']):
        return 'Invalid signature', 401
    
    # Process the webhook...

Política de reintentos

Las entregas de webhook fallidas se reintentan con retroceso exponencial y fluctuación:

  • Máximo de intentos: 5
  • Retrasos de reintento: 5 segundos, 15 segundos, 1 minuto, 3 minutos, 10 minutos
  • Fluctuación: Hasta un 10% de retraso adicional para prevenir el efecto de manada
  • Solo las respuestas HTTP 5xx y 429 activan reintentos
  • Las entregas agotan el tiempo después de 30 segundos

Las entregas de webhook se procesan de forma asíncrona y no afectan el rendimiento de ejecución del flujo de trabajo.

Mejores prácticas

  1. Estrategia de sondeo: Cuando consultes registros, utiliza paginación basada en cursores con order=asc y startDate para obtener nuevos registros de manera eficiente.

  2. Seguridad de webhook: Siempre configura un secreto de webhook y verifica las firmas para asegurar que las solicitudes provienen de Sim.

  3. Idempotencia: Utiliza la cabecera Idempotency-Key para detectar y manejar entregas duplicadas de webhook.

  4. Privacidad: Por defecto, finalOutput y traceSpans están excluidos de las respuestas. Habilítalos solo si necesitas los datos y comprendes las implicaciones de privacidad.

  5. Limitación de tasa: Implementa retroceso exponencial cuando recibas respuestas 429. Verifica la cabecera Retry-After para conocer el tiempo de espera recomendado.

Limitación de tasa

La API utiliza un algoritmo de cubo de tokens para limitar la tasa, proporcionando un uso justo mientras permite tráfico en ráfagas:

PlanSolicitudes/MinutoCapacidad de ráfaga
Free1020
Pro3060
Team60120
Enterprise120240

Cómo funciona:

  • Los tokens se recargan a una tasa de requestsPerMinute
  • Puedes acumular hasta maxBurst tokens cuando estás inactivo
  • Cada solicitud consume 1 token
  • La capacidad de ráfaga permite manejar picos de tráfico

La información del límite de tasa se incluye en los encabezados de respuesta:

  • X-RateLimit-Limit: Solicitudes por minuto (tasa de recarga)
  • X-RateLimit-Remaining: Tokens disponibles actualmente
  • X-RateLimit-Reset: Marca de tiempo ISO cuando los tokens se recargan nuevamente

Ejemplo: Sondeo para nuevos registros

let cursor = null;
const workspaceId = 'YOUR_WORKSPACE_ID';
const startDate = new Date().toISOString();

async function pollLogs() {
  const params = new URLSearchParams({
    workspaceId,
    startDate,
    order: 'asc',
    limit: '100'
  });
  
  if (cursor) {
    params.append('cursor', cursor);
  }
  
  const response = await fetch(
    `https://sim.ai/api/v1/logs?${params}`,
    {
      headers: {
        'x-api-key': 'YOUR_API_KEY'
      }
    }
  );
  
  if (response.ok) {
    const data = await response.json();
    
    // Process new logs
    for (const log of data.data) {
      console.log(`New execution: ${log.executionId}`);
    }
    
    // Update cursor for next poll
    if (data.nextCursor) {
      cursor = data.nextCursor;
    }
  }
}

// Poll every 30 seconds
setInterval(pollLogs, 30000);

Ejemplo: Procesamiento de webhooks

import express from 'express';
import crypto from 'crypto';

const app = express();
app.use(express.json());

app.post('/sim-webhook', (req, res) => {
  // Verify signature
  const signature = req.headers['sim-signature'];
  const body = JSON.stringify(req.body);
  
  if (!verifyWebhookSignature(body, signature, process.env.WEBHOOK_SECRET)) {
    return res.status(401).send('Invalid signature');
  }
  
  // Check timestamp to prevent replay attacks
  const timestamp = parseInt(req.headers['sim-timestamp']);
  const fiveMinutesAgo = Date.now() - (5 * 60 * 1000);
  
  if (timestamp < fiveMinutesAgo) {
    return res.status(401).send('Timestamp too old');
  }
  
  // Process the webhook
  const event = req.body;
  
  switch (event.type) {
    case 'workflow.execution.completed':
      const { workflowId, executionId, status, cost } = event.data;
      
      if (status === 'error') {
        console.error(`Workflow ${workflowId} failed: ${executionId}`);
        // Handle error...
      } else {
        console.log(`Workflow ${workflowId} completed: ${executionId}`);
        console.log(`Cost: $${cost.total}`);
        // Process successful execution...
      }
      break;
  }
  
  // Return 200 to acknowledge receipt
  res.status(200).send('OK');
});

app.listen(3000, () => {
  console.log('Webhook server listening on port 3000');
});
On this page

On this page

Start building today
Trusted by over 60,000 builders.
Build Agentic workflows visually on a drag-and-drop canvas or with natural language.
Get started