Taifa MailTaifa Mail Docs
Tracking & Analytics

Webhooks

Receive real-time HTTP callbacks when email events occur in Taifa Mail.

Webhooks let you receive real-time notifications about email events by POSTing JSON payloads to a URL you control. Instead of polling the API, your server gets notified the moment something happens.

Setting up a webhook

Via the dashboard

  1. Go to SettingsWebhooks.
  2. Click Add Webhook.
  3. Enter your endpoint URL (must be HTTPS).
  4. Select the events you want to receive.
  5. Click Save.

Via the API

curl -X POST https://govconnect.ke/v1/webhooks \
  -H "Authorization: Bearer tfm_k_YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://yourapp.com/webhooks/taifa-mail",
    "events": ["email.delivered", "email.bounced"]
  }'

The create response includes the webhook's id, url, events, secret, is_active flag, and created_at. Store the secret - you need it to verify incoming requests.

List all webhooks:

curl https://govconnect.ke/v1/webhooks \
  -H "Authorization: Bearer tfm_k_YOUR_API_KEY"

A webhook can be updated with PATCH /v1/webhooks/{id} (change url, events, or is_active) and removed with DELETE /v1/webhooks/{id}.

Events

A webhook subscribes to a list of event-type strings. Only events whose type is in the webhook's events array are delivered. Event types use the email.<event> form, for example email.sent, email.delivered, email.opened, email.clicked, email.bounced, email.failed.

Payload format

Each delivery is a POST with a JSON body shaped like this:

{
  "type": "email.delivered",
  "email_id": "a1b2c3d4-0000-0000-0000-000000000001",
  "data": {}
}

type is the event type, email_id is the email the event belongs to, and data carries any event-specific metadata.

Every request also carries these headers:

HeaderValue
X-TaifaMail-EventThe event type (same as type in the body).
X-TaifaMail-Delivery-IDThe unique ID of this delivery attempt.
X-TaifaMail-SignatureHMAC-SHA256 signature of the body (see below).

Retry policy

A delivery is treated as successful only when your endpoint responds with a 2xx status. A non-2xx response, a timeout (30-second limit), or a connection error counts as a failure and is retried:

AttemptDelay before retry
11 minute
25 minutes
330 minutes
42 hours
58 hours

After five retries are exhausted, Taifa Mail stops retrying that delivery and sends you an in-app notification so you can fix the endpoint. Every attempt is recorded - see the webhook's deliveries below.

Inspecting deliveries

Each attempt is logged as a delivery with its status, the HTTP response code, the attempt number, and the next scheduled retry.

curl "https://govconnect.ke/v1/webhooks/{webhook_id}/deliveries?page=0&limit=20" \
  -H "Authorization: Bearer tfm_k_YOUR_API_KEY"

Fetch a single attempt - including the full payload and response body - with GET /v1/webhooks/{webhook_id}/deliveries/{delivery_id}.

Verifying webhook signatures

Every webhook request includes an X-TaifaMail-Signature header. Verify it to ensure the request came from Taifa Mail and was not tampered with.

The header value is sha256= followed by the HMAC-SHA256 hex digest of the raw request body, signed with your webhook's secret (returned when you create the webhook).

import hmac
import hashlib
 
def verify_signature(body: bytes, signature: str, secret: str) -> bool:
    expected = "sha256=" + hmac.new(
        secret.encode(),
        body,
        hashlib.sha256,
    ).hexdigest()
    return hmac.compare_digest(expected, signature)
import crypto from "crypto";
 
function verifySignature(body, signature, secret) {
  const expected =
    "sha256=" +
    crypto.createHmac("sha256", secret).update(body).digest("hex");
  return crypto.timingSafeEqual(
    Buffer.from(expected),
    Buffer.from(signature)
  );
}

Always verify the X-TaifaMail-Signature header before processing webhook payloads. Without verification, an attacker could forge webhook requests to your endpoint.

Testing webhooks

Use a service like webhook.site to get a temporary URL for testing. Add it as a webhook endpoint and inspect the payloads it receives.

Click Send Test next to any webhook in the dashboard (or call POST /v1/webhooks/{webhook_id}/test) to queue a sample email.delivered delivery without sending a real email. The test delivery appears in the webhook's deliveries like any other.

On this page