Export events

Download your event history as a single CSV file — no pagination loop.

Every send, delivery, open, click, bounce and complaint lands in the event log. GET /v3/events reads it 300 rows at a time — fine for dashboards, painful for “give me everything from August”. This endpoint is the file-sized answer: start a background job, poll until it finishes, download one CSV. Typical uses: nightly warehouse/BI sync, compliance evidence (“prove the January invoices reached all 40,000 clients”), taking your data with you, and support investigations that span more than a few pages.

How it works

Three steps: 1) POST /v3/events/export with your filters — it answers immediately with an export_id. 2) Poll GET /v3/events/export/{id} until status is completed (the job runs in the background; large exports take a while). 3) Fetch the file from GET /v3/events/export/{id}/download. Generated files are kept for 7 days.

POST /v3/events/export

Body parameters (all optional)

ParameterTypeRequiredDescription
sinceISO-8601OptionalWindow start. Default: 30 days ago. May not reach past your plan’s event retention (30 days Free / 12 months paid) — an older start is rejected with retention_exceeded, never silently truncated.
untilISO-8601OptionalWindow end. Default: now.
eventsstring[]OptionalOnly these event types, e.g. ["bounced","complained"]. Default: all types.
recipientstringOptionalOnly events for this recipient address (exact match).
tagstringOptionalOnly events carrying this tag (event or parent message).
metadataobjectOptionalMetadata filters, e.g. {"order_id":"1234"} — matches the metadata you attached at send time. Up to 3 key/value pairs (keys up to 64 chars of letters, digits, dot, dash, underscore; values up to 200 chars; exact match), same semantics as the metadata[key] query filters on the events API.
formatstringOptionalcsv — the default and only format for now.

CSV columns

id, type, message_id, recipient, timestamp, tags, metadata, domain, created_at — the same field names the events API uses, so downstream schemas match. tags is semicolon-joined, metadata is the JSON object in one cell, domain is the sending domain. Cell values are escaped against Excel formula injection, so the file is safe to open directly in a spreadsheet.

Limits & idempotency

ParameterTypeRequiredDescription
Row cap1,000,000OptionalAn export matching more rows fails with a clear error_message — split the window (e.g. one export per week) and re-submit.
Concurrent jobs3OptionalAt most 3 event exports pending/running per account; a 4th returns 409 too_many_exports.
Rate limit10/minOptionalSame as the other export endpoints.
Duplicate submitsdedupedOptionalSubmitting an identical filter set while an equivalent job is pending or running returns the existing job’s export_id instead of starting a duplicate — retries are safe.

Responses

StatusDescription
202{ export_id, status } — poll GET /v3/events/export/{id}. An equivalent in-flight job is returned with its current status.
400retention_exceeded — since reaches past your plan’s event retention — or invalid filters.
409too_many_exports — 3 exports already pending or running.
429Rate limit exceeded (10 calls/minute).

Code examples

cURL
curl -X POST https://api.wemail.io/v3/events/export \
  -H "Authorization: Bearer afn_live_…" \
  -H "Content-Type: application/json" \
  -d '{
    "since":  "2026-08-01T00:00:00Z",
    "until":  "2026-08-31T23:59:59Z",
    "events": ["bounced", "complained"],
    "tag":    "billing"
  }'
# → 202 { "export_id": "7f3a2b1c-…", "status": "pending" }
Node.js
// Plain HTTP — SDK helpers for exports are on the way
const res = await fetch("https://api.wemail.io/v3/events/export", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${process.env.WEMAIL_API_KEY}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    since: "2026-08-01T00:00:00Z",
    until: "2026-08-31T23:59:59Z",
    events: ["bounced", "complained"],
    tag: "billing",
  }),
});
const { export_id } = await res.json();
Python
import os, requests

r = requests.post(
    "https://api.wemail.io/v3/events/export",
    headers={"Authorization": f"Bearer {os.environ['WEMAIL_API_KEY']}"},
    json={
        "since": "2026-08-01T00:00:00Z",
        "until": "2026-08-31T23:59:59Z",
        "events": ["bounced", "complained"],
        "tag": "billing",
    },
)
export_id = r.json()["export_id"]