BigStats

Setup guide · GreenArrow

Connect GreenArrow Engine to BigStats with event notifications.

Everything needed to stream GreenArrow's Event Notification System into BigStats: the webhook configuration, the event types you should send, example payloads for each one, and the alerts they drive.

Looking for the overview instead? GreenArrow reporting.

Step 01

Create an ingest key

In BigStats, open Settings → Ingestion and create a key for this GreenArrow install. Keys are workspace-scoped; use separate keys per node if you want to trace where events came from. Send the key as ?key= or the X-BigStats-Key header.

Endpoint

POST https://bigstats.email/api/public/ingest/greenarrow?key=<INGEST_KEY>

Step 02

Point the Event Notification System at it

  1. 01In GreenArrow Engine, open Settings → Event Notification System (or the Studio equivalent for your install).
  2. 02Add a new HTTP notification target pointing at your BigStats endpoint, with JSON as the payload format.
  3. 03Select the event types below. Enable POST with Content-Type: application/json and batching if your volume is high.
  4. 04Save and send a test notification, then reload the Settings page in BigStats to see the live feed confirm arrivals.

BigStats accepts one event per request or batches — a JSON array, newline-delimited JSON, or an object wrapper keyed by events, records or logs. Retries are safe: events are de-duplicated on event type, message id, recipient, timestamp and URL.

Step 03

Required event types

The four required events are the minimum for correct rates and alerting. Opens and clicks are optional and only arrive if tracking is enabled in GreenArrow.

GreenArrow eventBigStats eventStatusWhy it matters
injectioninjectedRequiredDenominator for delivery, bounce and complaint rates.
deliverydeliveredRequiredDelivery rate, ISP placement and delivery-rate-floor alerts.
bouncebouncedRequiredHard/soft/block classification and bounce-rate alerts.
deferraldeferredRequiredDeferral-rate and throttling alerts before a bounce wave.
spam_complaintcomplainedRecommendedFeedback-loop complaints and complaint-rate alerts.
unsubscribeunsubscribedRecommendedUnsubscribe-rate alerting and list-health reporting.
openopenedOptionalEngagement reporting; requires open tracking enabled.
clickclickedOptionalClick reporting with destination URL and user agent.
rejectionrejectedOptionalSuppression and pre-injection refusals, kept out of delivery stats.

Step 04

Example webhook payloads

Message accepted by GreenArrow Engine. Establishes the denominator for delivery, bounce and complaint rates.

injection → injected

{
  "type": "injection",
  "timestamp": "2026-08-11T14:02:11Z",
  "recipient": "jordan@gmail.com",
  "message_id": "01HZX9K7Q2W8N4C6",
  "campaign_id": "weekly-digest-2026-08",
  "mailing_id": "m-99231",
  "subject": "Your weekly delivery digest",
  "source_ip": "203.0.113.42",
  "vmta": "pool-transactional"
}

Batched events

{
  "events": [
    { "type": "delivery", "recipient": "a@gmail.com", "message_id": "m-1",
      "timestamp": "2026-08-11T14:02:18Z", "smtp_code": 250 },
    { "type": "bounce",   "recipient": "b@gmail.com", "message_id": "m-2",
      "timestamp": "2026-08-11T14:02:19Z", "smtp_code": 550,
      "diagnostic_code": "550 5.1.1 user unknown" }
  ]
}

Request formats

POST /api/public/ingest/greenarrow?key=ga_live_…
Content-Type: application/json
# the key may also be sent as the header: x-bigstats-key: ga_live_…

# a single notification …
{ "type": "delivery", "recipient": "jordan@gmail.com", "timestamp": 1785000012 }

# … or a batch: a JSON array, newline-delimited JSON,
# or an object wrapper using "events", "records" or "logs"

Responses

HTTP/1.1 200 OK
{ "ok": true, "received": 2 }

# failures
401 { "error": "missing ingest key" }      # no ?key= and no x-bigstats-key header
401 { "error": "invalid ingest key" }      # unknown or deactivated key
400 { "error": "no events found in payload" }
413 { "error": "too many events in one batch" }   # hard cap of 25,000 records per POST
500 { "error": "could not store events" }  # safe to retry; duplicates are dropped

Field mapping

What BigStats reads off each notification

GreenArrow fieldBigStats columnNotes
type / event_type / event / actionevent_typedelivery→delivered, bounce/hard_bounce/soft_bounce→bounced, deferral/tempfail→deferred, open→opened, click→clicked, unsubscribe→unsubscribed, spam_complaint/fbl→complained, rejection/blocked→rejected, injection→injected. Anything unrecognized lands as other.
timestamp / time / event_time / dateoccurred_atUnix seconds, milliseconds or an ISO 8601 string. Missing timestamps default to receipt time.
recipient / email / to / rcptrecipient / recipient_domain / isp_groupLowercased; the domain is split off and grouped into gmail · microsoft · yahoo · apple · corporate · other.
message_id / msg_id / queue_id / idmessage_idFirst match wins. Used in the dedupe hash with type, recipient, timestamp and url.
source_ip / sending_ip / vmta_ip / outbound_ipsending_ipThe /24 is derived from it for MTA clustering.
vmta / virtual_mta / binding / poolvmtaDrives the Shared Pools reporting.
remote_mta / receiving_mta / reporting_mta / mx_hostremote_mtaThe receiving MX that answered.
smtp_code (or parsed from the response)smtp_codeValidated to 200–599; falls back to the first 3-digit code inside the diagnostic text.
dsn / dsn_status / enhanced_statusdsnFalls back to an enhanced status code parsed out of the diagnostic, e.g. 5.1.1.
diagnostic_code / response / smtp_response / reasondiagnosticFull remote reply text retained for bounce forensics.
bounce_type / bounce_class / classificationbounce_type / bounce_categoryUsed as the declared hint; BigStats still classifies from the SMTP code and diagnostic into hard · soft · block plus a reason category.
campaign_id / campaign / mailing_name / list_idcampaign_idFirst match wins.
mailing_id / mailing / job_id / batch_idmailing_idFirst match wins.
subject / message_subjectsubjectShown on event drill-down and exports.
url / link / click_urlurlClick destination; also part of the click dedupe key.
user_agent / ua / clientuser_agentCaptured on opens and clicks.
(whole payload)rawThe complete JSON notification is retained on the event row for drill-down and export.

Step 05

Verify without storing anything

Run a dry run first: it authenticates your key and returns the normalized event exactly as BigStats would store it. Then remove dry_run=1 and watch the live feed on the Settings page confirm events arriving.

curl

curl -s -X POST \
  'https://bigstats.email/api/public/ingest/greenarrow?key=<INGEST_KEY>&dry_run=1' \
  -H 'Content-Type: application/json' \
  -d '{"type":"bounce","recipient":"test.user@gmail.com",
       "timestamp":"2026-08-11T14:04:02Z","source_ip":"203.0.113.42",
       "smtp_code":550,"dsn":"5.1.1",
       "diagnostic_code":"550 5.1.1 The email account that you tried to reach does not exist."}'

# dry_run authenticates and normalizes the payload but stores nothing:
# { "ok": true, "dry_run": true, "received": 1, "events": [ … ] }

Step 06

Alerts from GreenArrow events

Once events are flowing, alerting runs on them automatically — open Alert settings to set thresholds and recipients.

  • Bounce rate over threshold — workspace-wide and per receiving domain, with hard/soft/block breakdown.
  • Deferral spikes — deferral volume measured against a rolling 7-day baseline, so provider throttling surfaces early.
  • Complaint and unsubscribe rates — spam_complaint and unsubscribe events against delivered volume.
  • Delivery-rate floor — delivered vs injected dropping below your configured floor.
  • Escalation, Slack, outbound webhooks and the daily digest all work identically for GreenArrow-sourced alerts.