> ## Documentation Index
> Fetch the complete documentation index at: https://magica-adi.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Webhooks

> Signed outbound events for agent and tool lifecycle.

Register an HTTPS endpoint while signed in. `POST /api/webhook-endpoints` returns `secret` once (`gwhsec_…`). List and later reads never include it.

```json theme={null}
{
  "url": "https://example.com/galaxy-hooks",
  "events": ["agent.started", "agent.completed", "agent.failed", "tool.completed"]
}
```

`DELETE /api/webhook-endpoints/{endpointId}` removes it. `GET /api/webhook-endpoints` lists `id`, `url`, `events`, `isActive`, and `createdAt`.

## Events

| Event | When |
| - | - |
| `agent.started` | The orchestrator begins a turn |
| `agent.completed` | The turn finished `COMPLETE` |
| `agent.failed` | The turn finished `FAILED` or `CANCELLED`, or the task threw |
| `tool.completed` | A tool succeeded in the agent loop or on a public Magica route |

## Envelope

```json theme={null}
{
  "id": "wh:{endpointId}:{event}:{idempotency}",
  "event": "agent.completed",
  "createdAt": "2026-09-22T07:00:00.000Z",
  "data": {
    "chatId": "…",
    "runId": "…",
    "messageId": "…",
    "traceId": "…",
    "processId": "…",
    "status": "COMPLETE",
    "assistantMessageId": "…"
  }
}
```

`agent.started` uses `status: "QUEUED"`. `agent.failed` uses `FAILED` or `CANCELLED`, and a thrown turn adds `error`. `tool.completed` `data` includes `toolName`, `output`, `assets`, `creditCost`, and `durationMs`.

## Signature

<ParamField header="x-galaxy-signature" type="string">
  `sha256=<hex>`.
</ParamField>

<ParamField header="x-galaxy-timestamp" type="string">
  Unix seconds used in the HMAC.
</ParamField>

<ParamField header="x-galaxy-event" type="string">
  Event name.
</ParamField>

<ParamField header="x-galaxy-delivery-id" type="string">
  Delivery row id.
</ParamField>

Verify with the raw body, not a re-serialized object:

```text theme={null}
HMAC_SHA256(secret, `${timestamp}.${rawBody}`)
```

Compare the hex after `sha256=` with a constant-time check.

<Note>
  Each endpoint, event, and run (or tool call) is delivered once. A duplicate emit is not posted again. A timeout or non-2xx response is retried up to 4 times, waiting 1s, then 5s, then 15s. Each attempt is signed with a fresh timestamp. The row stays `PENDING` until the last failure, then `FAILED`. A failed delivery does not fail the agent turn.
</Note>


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.