Receive real-time notifications about email events
Webhooks allow you to receive real-time HTTP notifications when events occur in Ark. Instead of polling the API, configure a webhook endpoint and Ark will send events to your server as they happen.
Email successfully delivered to recipient’s server
Clears if exists
MessageDelayed
Temporary delivery issue (soft bounce), will retry
No
MessageDeliveryFailed
Permanent delivery failure (hard bounce)
Automatic
MessageBounced
NDR received after initial delivery acceptance
Manual only
MessageHeld
Email held for manual review (spam, suppression, etc.)
No
Bounce suppression:MessageDeliveryFailed (hard bounce) automatically adds the recipient to the suppression list. MessageBounced (NDR received) does NOT automatically suppress - handle this webhook to manually add addresses to your suppression list via the API if desired.
Return 200 quickly - Respond within 5 seconds to acknowledge receipt
Verify the signature - Always verify the X-Ark-Signature header
Process asynchronously - Queue events for processing if needed
Handle duplicates - Use the uuid field for idempotency
Python (FastAPI)
Node.js (Express)
Ruby (Sinatra)
Copy
from fastapi import FastAPI, Request, HTTPExceptionapp = FastAPI()@app.post('/webhooks/ark')async def handle_webhook(request: Request): # Verify signature first (see full example in guide) signature = request.headers.get('X-Ark-Signature') body = await request.body() if not verify_signature(body, signature): raise HTTPException(status_code=401, detail='Invalid signature') event = await request.json() # Acknowledge receipt immediately # Process event asynchronously process_webhook_event(event['event'], event['payload'], event['uuid']) return {'status': 'ok'}
Copy
app.post('/webhooks/ark', express.raw({ type: 'application/json' }), async (req, res) => { // Verify signature first (see full example in guide) const signature = req.headers['x-ark-signature']; const isValid = await verifySignature(req.body.toString(), signature); if (!isValid) { return res.status(401).send('Invalid signature'); } const { event, timestamp, uuid, payload } = JSON.parse(req.body); // Acknowledge receipt immediately res.status(200).send('OK'); // Process event asynchronously processWebhookEvent(event, payload, uuid);});
Copy
post '/webhooks/ark' do # Verify signature first (see full example in guide) signature = request.env['HTTP_X_ARK_SIGNATURE'] payload = request.body.read halt 401, 'Invalid signature' unless verify_signature(payload, signature) event = JSON.parse(payload) # Acknowledge receipt immediately, process async process_webhook_event(event['event'], event['payload'], event['uuid']) 'OK'end