Mager API

Webhooks

Get called when a task finishes, instead of polling for it.

Pass a callback_url when you create a task:

{
  "model": "image-generator",
  "input": { "prompt": "..." },
  "callback_url": "https://client.example.com/webhooks/mager"
}

Mager sends one POST to that URL once the task reaches finished or failed.

The payload

{
  "event": "generation.finished",
  "task_id": "cmagr01hxyz123",
  "status": "finished",
  "model": "image-generator",
  "result": [
    {
      "id": "result_01hxyz",
      "status": "SUCCESS",
      "file_url": "https://cdn.example.com/generated-image.png",
      "file_type": "image/png"
    }
  ],
  "error": null,
  "created_at": "2026-07-03T06:00:00.000Z",
  "completed_at": "2026-07-03T06:01:00.000Z"
}

event is generation.finished or generation.failed. On failure, error carries the reason and result is empty.

The request is sent as content-type: application/json with the user agent Mager-Developer-Webhooks/1.0.

Responding

Return any 2xx within 10 seconds. Anything else — a non-2xx status, a timeout, a connection error — counts as a failed delivery.

Acknowledge first, work second. Write the payload somewhere durable, return 200, and do the downloading and processing on your own time. Handlers that download the file before responding are the usual cause of timeout-driven retries.

Retries

A failed delivery is retried up to 3 attempts total, 60 seconds apart. After the third failure the delivery is marked FAILED and Mager stops.

Delivery state is visible on the task itself, under webhooks:

{
  "id": "delivery_01hxyz",
  "status": "RETRYING",
  "attempts": 2,
  "max_attempts": 3,
  "last_attempt_at": "2026-07-03T06:02:00.000Z",
  "next_retry_at": "2026-07-03T06:03:00.000Z",
  "last_status_code": 502,
  "last_error": "Request failed with status code 502"
}

If your endpoint was down for the whole retry window, queue a fresh delivery by hand:

curl https://api.mageran.ai/api/v1/generation-tasks/cmagr01hxyz123/webhooks/retry \
  --request POST \
  --header 'x-mager-api-key: YOUR_API_KEY'

The task must belong to your account, must have a callback_url, and must already be terminal.

Securing your endpoint

Mager does not sign webhook requests. There is no shared secret and no signature header, so your endpoint cannot verify from the request alone that Mager sent it.

Two things to do about that:

  1. Put a secret in the URL. Use a long, unguessable path or query value — https://client.example.com/webhooks/mager/8f2c… — and reject anything that does not match. It is coarse, but it stops anyone who does not already have the URL.
  2. Verify before you trust. Treat the payload as a hint, not as fact. Call GET /generation-tasks/{taskId} with your API key and use that response as the source of truth. This also covers the duplicate-delivery case: a retry after a timeout can arrive for a task you already handled.

Design the handler to be idempotent. Keying on task_id is enough.

When to use which

SituationApproach
Server-side job, you control the endpointWebhook
Local development, no public URLPolling
User is watching a progress barPoll, and update from webhooks

On this page