Docs·Reports

POST/api/v1/spreelytics/reports

Create a report

Saves a report and returns it. A report is a name plus a config: the report builder's own settings, so the app can open it in the builder and draw it on a dashboard. Every report sits on one dashboard, named by dashboardId, and you can pin its place on the grid with layout if you want to. Saving runs nothing; run the report with GET /reports/{reportId}/chart.

The config object:

  • chartType, interval and range are required. chartType is one of the builder's types: line (shown as Linear), bar, histogram, pie, metric, area, map, retention, funnel, conversion or sankey. interval, range, startDate, endDate, customDays, previous, breakdowns and globalFilters take what POST /chart takes, and a filter row may also carry the builder's own id. limit is stored but not applied when the report runs.
  • series holds the metrics, at most 20. Each needs an id (any string) and an event. segment says how it is measured: event (All events, the default), user (Unique users), session (Unique sessions), user_average (Average users), one_event_per_user (One event per user), or property_sum, property_average, property_max and property_min (Sum of property, Average of property, Max of property, Min of property) together with a property. type is event (the default), profile, cohort (with a segment id in cohortId) or formula. A formula series keeps an expression such as A/B in formula, naming the other series by their letters; the app works it out from their results, and the server never runs it.
  • To count several events as one metric, list them in events as { id, name } objects, the first one being the series' own event. For funnel, conversion and retention, this list holds the steps in order, all inside a single series. A filter in a series' filters that carries a member's id in event applies to that step only.
  • Options for one chart type: funnelWindowSeconds (funnel and conversion), funnelStrictOrder (funnel), retentionCriteria (retention), sankeyExclude plus stepsBefore and stepsAfter on each series (sankey), and stacked (histogram).
  • kind is chart unless you set it. Two other kinds have no series: breakdown, a tabbed list card like the Overview's, whose tabs go in tabKeys (channels, sources, referrers, utm_source, utm_medium, utm_campaign, utm_term, utm_content, browsers, os, devices, countries, regions, cities, pages, entry, exit, events), and metrics, a strip of headline numbers named in metrics (visitors, revenue, conversion-rate, revenue-per-visitor, bounce-rate, avg-session-duration, cohort-retention, online), where showChart: true adds the chart under them. Each needs at least one entry.
{
  "name": "Signups by source",
  "dashboardId": "DASHBOARD_ID",
  "config": {
    "chartType": "bar",
    "interval": "day",
    "range": "30d",
    "series": [{ "id": "a", "event": "signup", "segment": "user" }],
    "breakdowns": ["source"]
  }
}

That is a bar chart of the people who signed up in the last 30 days, split by source. The server checks the name, that a chart card has 1 to 20 series (a breakdown or metrics card needs at least one tab or number), that startDate comes before endDate when both are set, and that dashboardId is a dashboard in this audience. An unknown field answers 400. Everything else is stored as sent, so a config the engine cannot draw only shows up when you run it: try the chart with POST /chart first.

Needs the Editor or Admin role in the workspace that owns the audience. A Viewer gets 403.

Keys: an account key. Getting started explains both kinds.

Parameters

PropInTypeNotes
contactListIdquerystringThe audience id, a UUID. With an audience key it must be that key's own audience.

Request body

PropTypeNotes
namestringRequired. Trimmed, and a blank name answers 400.
configSpreelyticsSavedReportConfigRequired. The report builder's settings, described above.
dashboardIdstringRequired. The dashboard to put it on. It must be a dashboard in this audience, or the call answers 400.
layout?ReportLayoutSlotOptional. Its slot on the dashboard grid as { x, y, w, h }: x and w in columns of a 6-column grid (x from 0), y and h in rows. The app sizes a new card 3 by 2 and draws none smaller than 2 by 2. Leave it out and the app places the card itself.

Response

PropTypeNotes
idstringThe report id.
namestringThe report name.
dashboardIdstringThe dashboard it sits on. Every report sits on one.
configSpreelyticsSavedReportConfigThe saved settings, exactly as they were sent. POST /reports describes them.
layoutobjectIts slot on the dashboard grid as { x, y, w, h }, or null when the app places it.
createdAtstringWhen it was created. Only the create call answers in ISO 8601 (2026-09-30T09:00:00.000Z). Every other call returns the database form (2026-09-30 09:00:00+00), so parse both.
updatedAtstringWhen it last changed. Create and update calls answer in ISO 8601, lists and reads in the database form, as with createdAt.

Request

curl -X POST 'https://app.spreelytics.com/api/v1/spreelytics/reports?contactListId=…' \
  -H 'Authorization: Bearer YOUR_API_KEY' \
  -H 'Content-Type: application/json' \
  -d '{ … }'
const res = await fetch('https://app.spreelytics.com/api/v1/spreelytics/reports', {
  method: 'POST',
  headers: {
    Authorization: 'Bearer YOUR_API_KEY',
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({ /* see Request body above */ }),
});
const data = await res.json();
import requests

res = requests.post(
    "https://app.spreelytics.com/api/v1/spreelytics/reports",
    headers={"Authorization": "Bearer YOUR_API_KEY"},
    json={},  # see Request body above
)
data = res.json()

Response

{
  "id": "string",
  "name": "string",
  "dashboardId": "string",
  "config": {
    "kind": "chart",
    "chartType": "line",
    "interval": "minute",
    "range": "30min",
    "startDate": "string",
    "endDate": "string",
    "series": [
      {
        "id": "string",
        "type": "event",
        "event": "string",
        "events": [
          null
        ],
        "eventLabels": {},
        "stepsBefore": 0,
        "stepsAfter": 0,
        "displayName": "string",
        "segment": "event",
        "property": "string",
        "cohortId": "string",
        "filters": [
          null
        ],
        "formula": "string",
        "hideSeries": [
          null
        ]
      }
    ],
    "breakdowns": [
      "string"
    ],
    "breakdown": "string",
    "globalFilters": [
      {
        "id": "string",
        "name": "string",
        "operator": "is",
        "value": [
          null
        ],
        "event": "string"
      }
    ],
    "previous": true,
    "customDays": 0,
    "limit": 0,
    "funnelWindowSeconds": 0,
    "funnelStrictOrder": true,
    "retentionCriteria": "on",
    "sankeyExclude": [
      "string"
    ],
    "stacked": true,
    "tabKeys": [
      "string"
    ],
    "metrics": [
      "string"
    ],
    "showChart": true
  },
  "layout": "string",
  "createdAt": "string",
  "updatedAt": "string"
}

See your own numbers today.

Free up to 100k events a month · no credit card

Contact

Tell us what you need.

A real person reads these. We usually reply within one working day.

Or email us directly at contact@spreelytics.com.