Relay Rules
Relay rules define how alerts are processed and routed. Rules execute in order based on their order property.
Key Concepts
Section titled “Key Concepts”Groups: Parallel vs Sequential Execution
Section titled “Groups: Parallel vs Sequential Execution”The group field controls whether rules run simultaneously or sequentially:
- Same group = sequential (order 1, then 2, then 3)
- Different groups = parallel (run at the same time)
See Best Practices - Parallel vs Sequential for examples.
Idempotency
Section titled “Idempotency”Set externalKey on relay rules to make configuration idempotent and safe to re-run. See Best Practices.
Rule Types
Section titled “Rule Types”Schedule Notify
Section titled “Schedule Notify”Notify team members based on a schedule:
const rule = await client.relay.rules.create(relayId, { name: "Notify on-call engineer", ruleType: "schedule_notify", order: 1, config: { scheduleId: "sch_xyz123", }, enabled: true,});curl -X POST https://api.beeps.dev/v0/relay/rly_abc123/rules \ -H "Authorization: Bearer YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "name": "Notify on-call engineer", "ruleType": "schedule_notify", "order": 1, "config": { "scheduleId": "sch_xyz123" }, "enabled": true }'Webhook
Section titled “Webhook”Call an external webhook:
const rule = await client.relay.rules.create(relayId, { name: "Post to Slack", ruleType: "webhook", order: 2, config: { endpoint: "https://hooks.slack.com/services/YOUR/WEBHOOK/URL", method: "POST", headers: { "Content-Type": "application/json", }, payload: { text: "Alert received", severity: "high", }, timeout: 10000, // Optional: timeout in ms (default 30000) },});curl -X POST https://api.beeps.dev/v0/relay/rly_abc123/rules \ -H "Authorization: Bearer YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "name": "Post to Slack", "ruleType": "webhook", "order": 2, "config": { "endpoint": "https://hooks.slack.com/services/YOUR/WEBHOOK/URL", "method": "POST", "headers": { "Content-Type": "application/json" }, "payload": { "text": "Alert received" } } }'AI Agent
Section titled “AI Agent”Invoke an AI agent to handle the alert:
const rule = await client.relay.rules.create(relayId, { name: "Invoke Devin agent", ruleType: "agent", order: 1, config: { agentType: "devin", // or "cursor" integrationId: "int_abc123", // References stored credentials endpoint: "https://api.devin.ai/v3/organizations/sessions", // Optional override config: { // Agent-specific configuration priority: "high", }, pollInterval: 30000, // Check status every 30s (default) maxPollAttempts: 120, // Give up after 120 attempts (default) },});Cursor Agent
Section titled “Cursor Agent”Cursor requires a repository URL and can auto-create PRs:
const cursorRule = await client.relay.rules.create(relayId, { name: "Cursor Auto-Fix", ruleType: "agent", order: 1, config: { agentType: "cursor", integrationId: "int_cursor123", repository: "https://github.com/org/repo", // Required for Cursor autoCreatePr: true, // Default: true autoBranch: true, // Let Cursor auto-name the branch pollInterval: 30000, maxPollAttempts: 120, },});curl -X POST https://api.beeps.dev/v0/relay/rly_abc123/rules \ -H "Authorization: Bearer YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "name": "Invoke Devin agent", "ruleType": "agent", "order": 1, "config": { "agentType": "devin", "integrationId": "int_abc123", "pollInterval": 30000, "maxPollAttempts": 120 } }'Cursor Agent
Section titled “Cursor Agent”curl -X POST https://api.beeps.dev/v0/relay/rly_abc123/rules \ -H "Authorization: Bearer YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "name": "Cursor Auto-Fix", "ruleType": "agent", "order": 1, "config": { "agentType": "cursor", "integrationId": "int_cursor123", "repository": "https://github.com/org/repo", "autoCreatePr": true, "pollInterval": 30000, "maxPollAttempts": 120 } }'Managing Rules
Section titled “Managing Rules”List Rules
Section titled “List Rules”// List all rulesconst allRules = await client.relay.rules.list(relayId);
// Filter by enabled statusconst enabledRules = await client.relay.rules.list(relayId, { enabled: true,});
// Filter by rule typeconst webhookRules = await client.relay.rules.list(relayId, { ruleType: "webhook",});# List all rulescurl -X GET https://api.beeps.dev/v0/relay/rly_abc123/rules \ -H "Authorization: Bearer YOUR_API_KEY"
# Filter by enabled statuscurl -X GET "https://api.beeps.dev/v0/relay/rly_abc123/rules?enabled=true" \ -H "Authorization: Bearer YOUR_API_KEY"
# Filter by rule typecurl -X GET "https://api.beeps.dev/v0/relay/rly_abc123/rules?ruleType=webhook" \ -H "Authorization: Bearer YOUR_API_KEY"Get a Specific Rule
Section titled “Get a Specific Rule”const rule = await client.relay.rules.get(relayId, ruleId);console.log(`Rule: ${rule.name}, Order: ${rule.order}`);curl -X GET https://api.beeps.dev/v0/relay/rly_abc123/rules/rul_xyz789 \ -H "Authorization: Bearer YOUR_API_KEY"Update a Rule
Section titled “Update a Rule”const updatedRule = await client.relay.rules.update(relayId, ruleId, { name: "Updated rule name", enabled: false, config: { // Updated config },});curl -X PUT https://api.beeps.dev/v0/relay/rly_abc123/rules/rul_xyz789 \ -H "Authorization: Bearer YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "name": "Updated rule name", "enabled": false }'Delete a Rule
Section titled “Delete a Rule”await client.relay.rules.delete(relayId, ruleId);console.log("Rule deleted successfully");curl -X DELETE https://api.beeps.dev/v0/relay/rly_abc123/rules/rul_xyz789 \ -H "Authorization: Bearer YOUR_API_KEY"Reorder Rules
Section titled “Reorder Rules”const reorderedRules = await client.relay.rules.reorder(relayId, { rules: [ { id: "rul_first", order: 1 }, { id: "rul_second", order: 2 }, { id: "rul_third", order: 3 }, ],});
reorderedRules.forEach((rule) => { console.log(`${rule.order}: ${rule.name}`);});curl -X PUT https://api.beeps.dev/v0/relay/rly_abc123/rules/reorder \ -H "Authorization: Bearer YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "rules": [ {"id": "rul_first", "order": 1}, {"id": "rul_second", "order": 2}, {"id": "rul_third", "order": 3} ] }'Rule Groups
Section titled “Rule Groups”Organize related rules using the group property:
await client.relay.rules.create(relayId, { name: "Primary notification", ruleType: "schedule_notify", group: "primary", order: 1, config: { scheduleId: "sch_primary" },});
await client.relay.rules.create(relayId, { name: "Backup notification", ruleType: "schedule_notify", group: "backup", order: 2, config: { scheduleId: "sch_backup" },});Type Definitions
Section titled “Type Definitions”CreateRelayRuleInput
Section titled “CreateRelayRuleInput”type CreateRelayRuleInput = { externalKey?: string; name: string; ruleType: RelayRuleType; group?: string; order?: number; config: RelayRuleConfig; enabled?: boolean;};RelayRule
Section titled “RelayRule”type RelayRule = { id: string; organizationId: string; relayId: string; group: string; externalKey: string | null; name: string; order: number; ruleType: RelayRuleType; config: Record<string, unknown>; enabled: boolean; createdAt: string; updatedAt: string; deletedAt: string | null;};Best Practices
Section titled “Best Practices”See Best Practices for relay rule configuration guidelines.