Email report (single campaign)

Overview

Get email-channel KPIs (recipients, sent, delivered, opened, clicked, unsubscribed, failed, processed, tests/kiosk counts plus derived rates) and a fixed last-7-day daily timeseries for a single campaign.

Prerequisites

  • A bearer token. Callable with Account tokens.
  • The campaignId of the record you are targeting.

Base URL

EnvironmentURL
Productionhttps://production-api.shoutaboutus.com
Developmenthttps://development-api.shoutaboutus.com

Endpoint

GET /api/v1/campaign/{campaignId}/report/email

Authentication

  • Requires a bearer token in the Authorization: Bearer <bearer-token> header.

  • Who can call it: Account tokens.

  • The campaign is scoped to the caller, so a user can only read reports for campaigns owned by their own company (the account/location account).

  • A non-matching id returns 404 Campaign not found.

Rate limit

  • No rate limit.

Path parameters

ParameterTypeRequiredDescription
campaignIdintegerRequiredDigits only.

Query parameters

  • Query: start_date (string Y-m-d, optional) — KPI window start; defaults to the campaign's created_at start-of-day.
  • Query: end_date (string Y-m-d, optional) — KPI window end; defaults to now end-of-day. If start_date > end_date the two are swapped. Note: the timeseries.by_day block always covers the last 7 days (now-6 → end) regardless of the date filter.

Response

  • kpis.recipients_valid (int) — count of CampaignAudienceData with is_email_valid = 'valid', non-test.
  • kpis.sent / delivered / opened / clicked / unsubscribed (int) — counts of non-test rows whose respective *_at timestamp falls in the window.
  • kpis.failed (int) — rows with status = 'failed' within the window (failed_at).
  • kpis.processed (int) — non-test rows created in the window.
  • kpis.tests_sent (int) — is_test = true rows created in the window.
  • kpis.kiosk_sent (int) — non-test is_kiosk = true rows created in the window.
  • kpis.rates (object) — processed_rate, delivery_rate, open_rate, click_rate, unsubscribe_rate, sent_vs_audience_rate (floats, percent rounded to 2dp; 0 when denominator is 0).
  • timeseries.by_day (array) — one entry per day for the last 7 days, each { date (Y-m-d), sent, delivered, opened, clicked, unsubscribed, failed, processed } (ints).

200 Success · 200

{
  "data": {
    "status": "success",
    "data": {
      "kpis": {
        "recipients_valid": 1200,
        "sent": 1150,
        "delivered": 1100,
        "opened": 650,
        "clicked": 120,
        "unsubscribed": 8,
        "failed": 50,
        "processed": 1200,
        "rates": {
          "processed_rate": 100,
          "delivery_rate": 95.65,
          "open_rate": 56.52,
          "click_rate": 10.43,
          "unsubscribe_rate": 0.7,
          "sent_vs_audience_rate": 95.83
        },
        "tests_sent": 5,
        "kiosk_sent": 10
      },
      "timeseries": {
        "by_day": [
          {
            "date": "2026-06-20",
            "sent": 100,
            "delivered": 98,
            "opened": 60,
            "clicked": 12,
            "unsubscribed": 1,
            "failed": 2,
            "processed": 102
          }
        ]
      }
    }
  }
}

Errors

StatusMeaning
401The bearer token is missing, expired or invalid
404No record matches the id you sent
422The request failed validation — the response names the fields
500Unexpected server error

Example request

curl --request GET \
  --url "https://production-api.shoutaboutus.com/api/v1/campaign/123/report/email" \
  --header 'Authorization: Bearer <bearer-token>' \
  --header 'Accept: application/json'

Did this page help you?