Skip to main content
Use webhooks to receive events when an image task completes or fails. Webhooks are sent as JSON POST requests to the URLs you configure in your dashboard or per-request.

Events

Mynth currently sends the following events:
  • task.image.completed: Sent when all images in a task have finished generating.
  • task.image.failed: Sent if the entire task fails to process.

Headers

Each webhook request includes these headers to help you identify the event and verify its authenticity:
  • X-Mynth-Event: The name of the event (e.g., task.image.completed).
  • X-Mynth-Signature: HMAC SHA-256 signature for payload verification.

Security and Verification

Mynth supports two ways to configure webhooks, each with different security characteristics: Webhooks configured in your Dashboard are the most secure. They use a shared secret to sign payloads, allowing you to verify that the request truly came from Mynth using the X-Mynth-Signature header.

2. Custom Webhooks (Per-request)

You can also provide a webhook URL directly in your API request. These are useful for dynamic endpoints, but they do not support signature verification because there is no shared secret. Pro Tip: For custom webhooks, we recommend adding a unique token or secret to your URL search parameters to validate the request.
webhook: {
  enabled: true,
  custom: [{ url: "https://your-api.com/webhook?token=your_random_secret" }]
}

Signature Verification

To ensure webhooks are sent by Mynth (available only for Dashboard webhooks), you should verify the signature in the X-Mynth-Signature header. The signature header has the following format:
t=timestamp,v1=signature

Verification Steps

  1. Extract the timestamp and signature from the header.
  2. Concatenate the timestamp and the raw JSON request body with a . (dot): ${timestamp}.${rawBody}.
  3. Compute an HMAC SHA-256 hash of this string using your webhook secret as the key.
  4. Compare your computed signature with the v1 value in the header.

Node.js Example

import crypto from 'crypto';

function verifyWebhook(secret, header, rawBody) {
  const parts = header.split(',');
  const timestamp = parts.find(p => p.startsWith('t=')).split('=')[1];
  const signature = parts.find(p => p.startsWith('v1=')).split('=')[1];

  const signedPayload = `${timestamp}.${rawBody}`;
  const expectedSignature = crypto
    .createHmac('sha256', secret)
    .update(signedPayload)
    .digest('hex');

  // Use timingSafeEqual to prevent timing attacks
  return crypto.timingSafeEqual(
    Buffer.from(signature),
    Buffer.from(expectedSignature)
  );
}

Reliability and Retries

To ensure reliability, Mynth will automatically retry failing webhook deliveries with exponential backoff.

Automatic Disabling

If a webhook endpoint consistently fails (e.g., returns 5xx errors or times out) for 30 consecutive attempts, it will be automatically disabled to prevent system strain.
  • You can monitor the status of your webhooks in the dashboard.
  • Once you’ve fixed the issue on your server, you must manually re-enable the webhook in the Mynth dashboard.

Payloads

Task Completed (task.image.completed)

{
  "event": "task.image.completed",
  "task": { "id": "task_123" },
  "request": {
    "prompt": { 
      "positive": "A futuristic cityscape", 
      "magic": true 
    },
    "model": "black-forest-labs/flux.1-dev",
    "size": "landscape",
    "count": 1,
    "metadata": {
      "internal_id": "user_456"
    }
  },
  "result": {
    "images": [
      {
        "status": "succeeded",
        "url": "https://cdn.mynth.io/img/...",
        "provider_id": "fal-ai",
        "cost": "0.03"
      }
    ],
    "cost": { "images": "0.03", "total": "0.033", "fee": "0.003" },
    "model": { 
      "id": "black-forest-labs/flux.1-dev", 
      "settings": { "resolution": { "width": 1024, "height": 768 } } 
    },
    "magic": { 
      "prompt": { "positive": "A detailed futuristic cityscape with neon lights..." } 
    }
  }
}

Task Failed (task.image.failed)

{
  "event": "task.image.failed",
  "task": { "id": "task_123" },
  "request": {
    "prompt": { "positive": "..." },
    "model": "black-forest-labs/flux.1-dev"
  },
  "errors": [
    { "code": "provider_error", "message": "The upstream provider is currently unavailable" }
  ]
}

Registering Webhooks

You can configure global webhooks in the Dashboard or pass custom URLs per request:
const task = await mynth.generate({
  prompt: "A charcoal sketch of a seaside cafe",
  webhook: {
    enabled: true,
    custom: [{ url: "https://example.com/webhooks/mynth" }],
  },
});