CoordinateDocs
Build · Actions
Build

Webhooks, API requests, emitted events, and presets: what a trigger does.

A trigger's then is one action or a list; every action runs.

Webhook

json
{"webhook": {"url": "https://example.com/hooks/coordinate", "signing_secret": "secret:HOOK"}}

For a receiver built for Coordinate. The body is the firing as JSON: {version: "coordinate.webhook.v1", delivery_id, trigger, firing, event, rows, row, about}. With a signing secret, Coordinate-Signature: t=<unix>,v1=<hex HMAC-SHA256 of "<t>.<body>">.

API request

json
{"request": {"method": "POST", "url": "https://api.linear.app/graphql",
   "auth": {"bearer": "secret:LINEAR"},
   "body": {"query": "mutation($t: String!) { issueCreate(input: {teamId: \"T\", title: $t}) { issue { id } } }", "variables": {"t": "{{event.payload.title}}"}}},
 "record": {"issue_id": "data.issueCreate.issue.id"}}

For any API, in its own shape. auth is {"bearer": "secret:X"}, {"headers": {"x-api-key": "secret:X"}}, or {"connection": "github" | "<source>"} to use a connected source's credential. The host can't be templated, and a secret is only ever sent to the host it was first used with. With {"connection": "github"}, Coordinate uses the GitHub App installation for the account the URL names (/repos/{owner}/…), for any endpoint the app's permissions cover: metadata (stars, releases, topics), contents, pull requests, checks, and Actions. Reads (GET) of public repositories the app isn't installed on use Coordinate's own GitHub credentials, so watching any public repository needs no token. Only a private repository the app can't reach needs {"bearer": "secret:NAME"} with a personal access token. record copies fields from the JSON response into action.succeeded.

Emit

json
{"emit": {"type": "deploys.flaky", "payload": {"repo": "{{event.payload.repo}}"}}}

Appends an event on source coordinate right away, for other triggers and agents to react to.

Messages

Send a message to wherever you'll see it. Email to yourself needs no setup; for the others, store the credential as a secret first (Settings → Secrets, or coordinate secret set NAME).

json
{"slack": {"webhook_url": "secret:SLACK_WEBHOOK", "message": "Deploy failed: {{event.payload.url}}"}}
{"discord": {"webhook_url": "secret:DISCORD_WEBHOOK", "message": "Deploy failed: {{event.payload.url}}"}}
{"email": {"subject": "{{trigger.name}}", "message": "Deploy failed: {{event.payload.url}}"}}
{"email": {"api_key": "secret:RESEND", "from": "Coordinate <alerts@your-domain.com>", "to": ["team@example.com"], "subject": "{{trigger.name}}", "message": "Deploy failed: {{event.payload.url}}"}}
{"poke": {"message": "Deploy failed: {{event.payload.url}}", "api_key": "secret:POKE"}}
  • Slack: in Slack, create an app with an incoming webhook for the channel (api.slack.com/apps → Incoming Webhooks) and store the https://hooks.slack.com/… URL as a secret. The URL is the credential, so it is never shown again.
  • Discord: channel settings → Integrations → Webhooks → New webhook → Copy URL, and store the https://discord.com/api/webhooks/… URL as a secret. Mentions in the message don't ping anyone.
  • Email: with just subject and message, Coordinate sends it from its own address to your workspace's email (Settings → Email), up to 50 a day. To email anyone else, or more, add your Resend API key as api_key, a sender on a domain verified in Resend as from, and the recipients as to.
  • Poke: a text through Poke, framed so Poke knows it came from an automation.
  • Anything else (ntfy, PagerDuty, Telegram, your own app): a webhook with the whole firing as JSON, or a request in the API's own shape.

Claude agent

  • {"claude_agent": {"api_key": "secret:ANTHROPIC", "agent_id": "...", "environment_id": "...", "vault_ids": [...], "repo": "owner/name", "repo_token": "secret:GH", "rubric": "...", "message": "..."}}: starts a Claude Managed Agents session with the task as an outcome, the firing as data, and instructions to report back with emit (agent.completed or agent.failed with the firing id as correlation_id). The session id is recorded.

Templates

{{event.payload.x}}, {{event.id}}, {{rows}}, {{row.x}}, {{trigger.name}}, {{firing.id}}, with |lower and |upper. A string that is exactly one placeholder keeps the value's type, so "{{event.payload}}" stays an object.

Delivery

Webhooks, requests, messages, and agent sessions are delivered at least once: up to 10 attempts over 24 hours, retrying network errors, 408, 429, and 5xx with backoff (honoring Retry-After). Redirects are not followed. A failure that won't recover becomes an alert. list_actions shows recent runs; retry_action sends a failed one again.