> ## Documentation Index
> Fetch the complete documentation index at: https://docs.mailchannels.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Webhook retries and delivery behavior

> Design reliable webhook consumers with MailChannels webhook status tracking, validation, and batch resend.

Your webhook receiver should assume that delivery events are operational data. Store them before running business logic,
process them asynchronously, and make handlers idempotent.

## Success and failure

MailChannels treats a webhook request as successful when your endpoint returns a `2xx` HTTP status. Other responses are
recorded by status category, including `1xx`, `3xx`, `4xx`, `5xx`, and `no_response`.

Use the webhook batch API to inspect recent webhook batches. If no time range is supplied, the API returns batches from
the last 3 days. If you provide `created_after` and `created_before`, the range must not exceed 31 days.

<CodeGroup>
  ```bash cURL theme={null}
  #!/usr/bin/env bash
  # List webhook batches from the last 3 days.
  set -u
  : "${MAILCHANNELS_API_KEY:?Set MAILCHANNELS_API_KEY before running}"

  curl -X GET "https://api.mailchannels.net/tx/v1/webhook-batch" \
    -H "X-Api-Key: $MAILCHANNELS_API_KEY"
  ```

  ```javascript Node.js theme={null}
  import { MailChannels } from "mailchannels-sdk";

  const { MAILCHANNELS_API_KEY } = process.env;
  if (!MAILCHANNELS_API_KEY) throw new Error("Set MAILCHANNELS_API_KEY before running");

  const mailchannels = new MailChannels(MAILCHANNELS_API_KEY);

  const { data, error } = await mailchannels.webhooks.batches();

  if (error) {
    console.error("List webhook batches failed:", error);
    process.exit(1);
  }
  console.log(data);
  ```

  ```python Python theme={null}
  import os
  import sys

  import mailchannels

  if not os.environ.get("MAILCHANNELS_API_KEY"):
      sys.exit("Set MAILCHANNELS_API_KEY before running")

  # List webhook batches from the last 3 days.
  response = mailchannels.Webhooks.batches()

  print(response)
  ```

  ```php PHP theme={null}
  <?php

  require_once __DIR__ . '/vendor/autoload.php';

  use MailChannels\Client;

  $api_key = getenv('MAILCHANNELS_API_KEY') or exit("Error: MAILCHANNELS_API_KEY is not set\n");

  $client = new Client(apiKey: $api_key);

  // List webhook batches from the last 3 days.
  $response = $client->webhooks->batches();

  print_r($response->toArray());
  ```
</CodeGroup>

## Replay failed batches

After you fix a receiver problem, you can resend a specific batch.

<CodeGroup>
  ```bash cURL theme={null}
  #!/usr/bin/env bash
  # Resend a specific webhook batch.
  set -u
  : "${MAILCHANNELS_API_KEY:?Set MAILCHANNELS_API_KEY before running}"
  : "${BATCH_ID:?Set BATCH_ID before running}"

  curl -X POST "https://api.mailchannels.net/tx/v1/webhook-batch/$BATCH_ID/resend" \
    -H "X-Api-Key: $MAILCHANNELS_API_KEY"
  ```

  ```javascript Node.js theme={null}
  import { MailChannels } from "mailchannels-sdk";

  const { MAILCHANNELS_API_KEY, BATCH_ID } = process.env;
  if (!MAILCHANNELS_API_KEY) throw new Error("Set MAILCHANNELS_API_KEY before running");
  if (!BATCH_ID) throw new Error("Set BATCH_ID to the ID of the batch to resend");

  const mailchannels = new MailChannels(MAILCHANNELS_API_KEY);

  const { data, error } = await mailchannels.webhooks.resendBatch(Number(BATCH_ID));

  if (error) {
    console.error("Resend webhook batch failed:", error);
    process.exit(1);
  }
  console.log(data);
  ```

  ```python Python theme={null}
  import os
  import sys

  import mailchannels

  if not os.environ.get("MAILCHANNELS_API_KEY"):
      sys.exit("Set MAILCHANNELS_API_KEY before running")

  batch_id_str = os.environ.get("BATCH_ID")
  if not batch_id_str:
      sys.exit("Set BATCH_ID before running")

  # Resend a specific webhook batch.
  response = mailchannels.Webhooks.resend_batch(int(batch_id_str))

  print(response)
  ```

  ```php PHP theme={null}
  <?php

  require_once __DIR__ . '/vendor/autoload.php';

  use MailChannels\Client;

  $api_key  = getenv('MAILCHANNELS_API_KEY') or exit("Error: MAILCHANNELS_API_KEY is not set\n");
  $batch_id = getenv('BATCH_ID') or exit("Error: BATCH_ID is not set\n");

  $client = new Client(apiKey: $api_key);

  $response = $client->webhooks->resendBatch((int) $batch_id);

  print_r($response->toArray());
  ```
</CodeGroup>

<Warning>
  A successful resend API response means MailChannels made the resend attempt and captured the endpoint response. It does
  not mean your endpoint returned a `2xx` status. Check the response body and your receiver logs.
</Warning>

## Test delivery

Use webhook validation before production launch and after endpoint changes. Validation sends a test event with your customer
handle, a test sender, a test event type, and a generated `smtp_id`.
