Skip to main content

Overview

Webhooks let you receive HTTP POST notifications when events happen during a workflow run. Instead of polling GET /v1/runs/{runId}, provide a URL and GalaxyAI pushes events to you automatically. Delivery is powered by Svix — automatic retries, HMAC-SHA256 signatures, and delivery logging included.

Quick Start

Add a webhook object to your POST /v1/runs request:
curl -X POST https://app.galaxy.ai/api/v1/runs \
  -H "Authorization: Bearer gx_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{
    "workflowId": "wf_abc123",
    "webhook": {
      "url": "https://your-app.com/webhooks/galaxyai",
      "events": ["run.completed", "run.failed"],
      "metadata": { "orderId": "order_456" }
    }
  }'
When the run finishes, GalaxyAI POSTs to your URL:
{
  "success": true,
  "type": "run.completed",
  "runId": "cuid_abc123",
  "workflowId": "cuid_def456",
  "data": { "status": "COMPLETED", "completedNodes": 5, "failedNodes": 0 },
  "metadata": { "orderId": "order_456" },
  "error": null,
  "createdAt": "2026-02-18T12:00:00.000Z"
}
Handle it on your server:
app.post("/webhooks/galaxyai", (req, res) => {
  res.status(200).send("OK"); // Respond immediately

  const event = req.body;

  if (event.type === "run.completed") {
    // Fetch full results
    fetchRunResults(event.runId);
  }

  if (event.type === "run.failed") {
    console.error("Run failed:", event.error);
  }
});

Configuration

FieldTypeRequiredDescription
urlstringYesHTTPS endpoint to receive webhook POST requests
eventsstring[]NoEvent types to subscribe to. Omit to receive all events
metadataobjectNoArbitrary key-value pairs echoed back in every payload
headersobjectNoCustom headers included in webhook POST requests

Event Types

EventFires when
run.startedWorkflow begins executing
run.completedAll nodes finished successfully
run.failedOne or more nodes failed
run.canceledRun was canceled by user
node.completedA single node finished successfully
node.failedA single node failed
Common patterns:
Use caseEvents
Just the final result["run.completed", "run.failed"]
Track progress["node.completed", "run.completed", "run.failed"]
Failures only["run.failed", "node.failed"]

Payload

FieldTypeDescription
successbooleantrue for success events, false for failures
typestringEvent type (e.g. run.completed)
runIdstringWorkflow run ID
workflowIdstringWorkflow definition ID
dataobjectEvent-specific data (status, nodeId, nodeType, etc.)
metadataobject | nullYour custom metadata, echoed back
errorstring | nullError message for failure events
createdAtstringISO 8601 timestamp

Security

Every webhook is signed with HMAC-SHA256 via Svix. Verify signatures using the Svix SDK:
import { Webhook } from "svix";

// Use raw body, not parsed JSON
app.use("/webhooks/galaxyai", express.raw({ type: "application/json" }));

const wh = new Webhook("whsec_your_signing_secret");

app.post("/webhooks/galaxyai", (req, res) => {
  try {
    const payload = wh.verify(req.body, {
      "svix-id": req.headers["svix-id"],
      "svix-timestamp": req.headers["svix-timestamp"],
      "svix-signature": req.headers["svix-signature"],
    });
    res.status(200).send("OK");
    // Process payload...
  } catch (err) {
    res.status(400).send("Invalid signature");
  }
});
Install the Svix SDK: npm install svix (Node.js) or pip install svix (Python).

Retries

If your server is down or returns a non-2xx response, Svix retries automatically:
AttemptDelay
1st retry~5 seconds
2nd retry~5 minutes
3rd retry~30 minutes
4th retry~2 hours
5th retry~8 hours
After 6 total attempts over ~3 days, the message is marked as failed.
Return 200 OK immediately and process asynchronously. If your handler takes longer than 30 seconds, Svix will retry — causing duplicate deliveries.