Project engagement rollup

GET/v1/stats

Secret key — sk_… or sk_test_… · Base URL https://api.volanea.com

Sends, delivery, opens, clicks, bounces and unsubscribes for the whole project over a window, with the previous window alongside for comparison and a gap-free daily series for charting.

Test and live are separate populations, and which one you get is decided by the key you authenticate with rather than by a parameter — a sk_test_… key can never report production figures. This matters more than it sounds: in a project that has been integrated against, more than half the rows in the send log can be test sends, and totalling GET /v1/emails without filtering them produces a delivery rate that is wrong by tens of points.

Rates compare in points, sends compare in percent. An open rate moving 35% → 38% is reported as openPoints: 3, because "open rate up 8%" is ambiguous and "up 3 points" is not. sentPercent is a true percentage change, and is null rather than 0 when the previous window had no sends at all — those are different facts.

delivered counts every message that reached the mailbox, so it includes the ones that went on to be opened and clicked. Statuses only move forward, so each stage necessarily contains the ones past it.

Query parameters

  • daysinteger

    Window length in days (1–365, default 30). The comparison window is the same length immediately before it.

Response

The rollup.

  • windowobject
    • daysinteger
    • fromdate-time
    • todate-time
  • testModeboolean

    Which population these numbers describe, derived from the key.

  • totalsobject
    • sentinteger
    • deliveredinteger
    • openedinteger
    • clickedinteger
    • bouncedinteger
    • complainedinteger
    • failedinteger
    • unsubscribedinteger
  • ratesobject

    Percentages. `delivery` and `bounce` are of `sent`; `open`, `click` and `unsubscribe` are of `delivered`.

    • deliverynumber
    • opennumber
    • clicknumber
    • bouncenumber
    • unsubscribenumber
  • previousobject

    The same measures for the preceding window of equal length.

  • changeobject
    • sentPercentnumber | null

      Percentage change in volume; null when the previous window had no sends.

    • deliveryPointsnumber
    • openPointsnumber
    • clickPointsnumber
  • dailyobject[]

    One entry per day, oldest first, split by source. Days with no sends are present with zeros so a chart has no holes.

    • daystring

      YYYY-MM-DD.

    • transactionalinteger
    • campaigninteger
    • workflowinteger
    • inboundinteger
    • totalinteger

Errors

Every failure returns the standard envelope — branch on `code`, never on the wording of `error`.

  • 401Missing or invalid API key.
  • 422Request validation failed (code `validation_error`, 422).

Request

curl https://api.volanea.com/v1/stats?days=30 \
  -H "Authorization: Bearer sk_..."

Response

200 · application/json

{
  "success": true,
  "data": {
    "window": {
      "days": 1,
      "from": "hello@yourdomain.com",
      "to": "ada@example.com"
    },
    "testMode": true,
    "totals": {
      "sent": 1,
      "delivered": 1,
      "opened": 1,
      "clicked": 1,
      "bounced": 1,
      "complained": 1,
      "failed": 1,
      "unsubscribed": 1
    },
    "rates": {
      "delivery": 1,
      "open": 1,
      "click": 1,
      "bounce": 1,
      "unsubscribe": 1
    },
    "previous": {},
    "change": {
      "sentPercent": 1,
      "deliveryPoints": 1,
      "openPoints": 1,
      "clickPoints": 1
    },
    "daily": [
      {
        "day": "<day>",
        "transactional": 1,
        "campaign": 1,
        "workflow": 1,
        "inbound": 1,
        "total": 1
      }
    ]
  }
}

92 endpoints · OpenAPI document