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
| Field | Type | Required | Description |
|---|
url | string | Yes | HTTPS endpoint to receive webhook POST requests |
events | string[] | No | Event types to subscribe to. Omit to receive all events |
metadata | object | No | Arbitrary key-value pairs echoed back in every payload |
headers | object | No | Custom headers included in webhook POST requests |
Event Types
| Event | Fires when |
|---|
run.started | Workflow begins executing |
run.completed | All nodes finished successfully |
run.failed | One or more nodes failed |
run.canceled | Run was canceled by user |
node.completed | A single node finished successfully |
node.failed | A single node failed |
Common patterns:
| Use case | Events |
|---|
| Just the final result | ["run.completed", "run.failed"] |
| Track progress | ["node.completed", "run.completed", "run.failed"] |
| Failures only | ["run.failed", "node.failed"] |
Payload
| Field | Type | Description |
|---|
success | boolean | true for success events, false for failures |
type | string | Event type (e.g. run.completed) |
runId | string | Workflow run ID |
workflowId | string | Workflow definition ID |
data | object | Event-specific data (status, nodeId, nodeType, etc.) |
metadata | object | null | Your custom metadata, echoed back |
error | string | null | Error message for failure events |
createdAt | string | ISO 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:
| Attempt | Delay |
|---|
| 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.