Insights API

Read what happened after you sent something. Insights answers three kinds of question: what did I send (names), how did it perform overall (aggregated), and what happened to each recipient (details) — across email, SMS, landing pages and surveys.

The channel is in the path, not a parameter

Most operations exist once per channel: /v1/email/distribution/names and /v1/sms/distribution/names take the same parameters and return the same shape. Pick the path for the channel you want — there is no channel query parameter.

Distributions and campaigns are different things

A distribution is one send you made — a batch of email or SMS. A campaign is a piece of content — a landing page, an email campaign or a survey — that people arrive at. They have separate names, aggregated and details endpoints, and the ids are not interchangeable.

Download for AI review

Copy or download this guide as Markdown to paste into an AI assistant for help integrating against it.

Environment

You are reading the guide for the host that served this page. The badge in the header and every example below already point at it — nothing to substitute by hand, and no other environment's addresses appear on this page.

PropertyValue
Environment
Base URLhttps://insights-dev.jirafix.net
All pathsare under /v1

Authentication

Every endpoint needs a bearer token, and this host does not issue one. Exchange your credentials at the Authenticate API — on this environment that is https://authenticate-dev.jirafix.net — then send what it returns as Authorization: Bearer <access_token> on each request here.

Keep your credentials on your server

Analytics data describes your customers. Credentials embedded in a browser page or a mobile app are published credentials — request the token from your own backend and never ship it to a client.

POST https://authenticate-dev.jirafix.net/v1/token

Exchanges your credentials for an access token.

Tokens last 3600 seconds by default. Request a new one when it expires — there is no separate refresh call, though the response does include a refresh_token. Full detail is on the Authenticate guide at https://authenticate-dev.jirafix.net/docs.

Parameters

NameTypeRequiredDescription
usernamestringYesThe account's username, usually an email address.
passwordstringYesThe account's password. Server-side only.
privatetokenstringYesYour account's private token, from the portal's configuration section. Note the spelling — one word, all lower case.
validityintegerNoHow long the token should last, in seconds. Defaults to 3600.

Responses

StatusMeaning
200Returns access_token, refresh_token, token_type and expires_in.
400The body was missing or a required field was absent.
401The username, password or private token was not accepted.
# 1. get a token from the Authenticate host
ACCESS_TOKEN=$(curl -s -X POST https://authenticate-dev.jirafix.net/v1/token \
  -H "Content-Type: application/json" \
  -d '{"username":"you@yourcompany.com","password":"'"$OLANZO_PASSWORD"'","privatetoken":"'"$OLANZO_PRIVATE_TOKEN"'"}' \
  | jq -r .access_token)

# 2. spend it here
curl -X GET "https://insights-dev.jirafix.net/v1/email/distribution/names?pageIndex=1&pageSize=20" \
  -H "Authorization: Bearer $ACCESS_TOKEN"
using var auth = new HttpClient { BaseAddress = new Uri("https://authenticate-dev.jirafix.net") };

var tokenResponse = await auth.PostAsJsonAsync("/v1/token", new
{
    username = "you@yourcompany.com",
    password = Environment.GetEnvironmentVariable("OLANZO_PASSWORD"),
    privatetoken = Environment.GetEnvironmentVariable("OLANZO_PRIVATE_TOKEN"),
});

// the property is access_token, not accessToken
var payload = await tokenResponse.Content.ReadFromJsonAsync<JsonElement>();
var token = payload.GetProperty("access_token").GetString();

using var api = new HttpClient { BaseAddress = new Uri("https://insights-dev.jirafix.net") };
api.DefaultRequestHeaders.Authorization =
    new AuthenticationHeaderValue("Bearer", token);

var response = await api.SendAsync(
    new HttpRequestMessage(HttpMethod.Get, "/v1/email/distribution/names?pageIndex=1&pageSize=20"));
// 1. get a token from the Authenticate host
const tokenResponse = await fetch("https://authenticate-dev.jirafix.net/v1/token", {
  method: "POST",
  headers: { "Content-Type": "application/json" },
  body: JSON.stringify({
    username: "you@yourcompany.com",
    password: process.env.OLANZO_PASSWORD,
    privatetoken: process.env.OLANZO_PRIVATE_TOKEN,
  }),
});

// note the underscore — accessToken is undefined
const { access_token } = await tokenResponse.json();

// 2. spend it here
const response = await fetch("https://insights-dev.jirafix.net/v1/email/distribution/names?pageIndex=1&pageSize=20", {
  method: "GET",
  headers: { Authorization: `Bearer ${access_token}` },
});
import os, requests

# 1. get a token from the Authenticate host
token_response = requests.post(
    "https://authenticate-dev.jirafix.net/v1/token",
    json={
        "username": "you@yourcompany.com",
        "password": os.environ["OLANZO_PASSWORD"],
        "privatetoken": os.environ["OLANZO_PRIVATE_TOKEN"],
    },
)

# note the underscore — "accessToken" raises KeyError
access_token = token_response.json()["access_token"]

# 2. spend it here
response = requests.get(
    "https://insights-dev.jirafix.net/v1/email/distribution/names?pageIndex=1&pageSize=20",
    headers={"Authorization": f"Bearer {access_token}"},
)
200 OK

{
  "access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
  "refresh_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
  "token_type": "Bearer",
  "expires_in": 3600
}
The response is snake_case

The fields are access_token, refresh_token, token_type and expires_in — not accessToken or expiresIn. Reading the camelCase spelling gives you nothing, with no error to explain it.

Use the Authenticate host for this same environment

A token carries the API domains it is allowed to reach. One issued by a different environment's Authenticate host is rejected here with a 401 that reads like bad credentials, so check the pair before you check your password: this page is https://insights-dev.jirafix.net and its Authenticate host is https://authenticate-dev.jirafix.net.

Paging through results

Almost every list endpoint pages with pageIndex and pageSize, both 1–1000, defaulting to page 1 and 100 per page. The response wraps the rows in a data array alongside the totals.

Two endpoints page differently

Recipients by event criteria is cursor-based: no pageIndex, a pageSize capped at 500, and a nextCursor you pass back to continue. Paging it like the others silently gets you page 1 every time.

Revenue transactions caps pageSize at 100 and defaults to 50, because it is a far heavier query than the analytics above.

Your first query

Analytics here is a two-step flow: list what you sent to get an id, then ask about that id.

curl -X GET "https://insights-dev.jirafix.net/v1/email/distribution/names?pageIndex=1&pageSize=20" \
  -H "Authorization: Bearer <your-token>"
curl -X GET "https://insights-dev.jirafix.net/v1/email/distribution/aggregated?id=3fa85f64-5717-4562-b3fc-2c963f66afa6" \
  -H "Authorization: Bearer <your-token>"

List your sends

Start here. These return the sends on the account with their ids, which every other distribution endpoint needs.

GET /v1/email/distribution/names

Lists email sends with their ids and names.

Parameters

NameTypeRequiredDescription
pageIndexintegerNoPage to return, 1–1000. Defaults to 1.
pageSizeintegerNoRows per page, 1–1000. Defaults to 100.

Responses

StatusMeaning
200The rows, with paging totals alongside them.
400A required parameter is missing, or a value is out of range — pageIndex and pageSize must be 1–1000.
401Missing, expired or invalid bearer token.
curl -X GET "https://insights-dev.jirafix.net/v1/email/distribution/names?pageIndex=1&pageSize=20" \
  -H "Authorization: Bearer <your-token>"
GET /v1/sms/distribution/names

Lists SMS sends with their ids and names.

Parameters

NameTypeRequiredDescription
pageIndexintegerNoPage to return, 1–1000. Defaults to 1.
pageSizeintegerNoRows per page, 1–1000. Defaults to 100.

Responses

StatusMeaning
200The rows, with paging totals alongside them.
400A required parameter is missing, or a value is out of range — pageIndex and pageSize must be 1–1000.
401Missing, expired or invalid bearer token.
curl -X GET "https://insights-dev.jirafix.net/v1/sms/distribution/names?pageIndex=1&pageSize=20" \
  -H "Authorization: Bearer <your-token>"

List your campaigns

The campaign equivalent. The id you get back is what the campaign aggregated and details endpoints expect — it is not a distribution id.

GET /v1/landingpage/campaign/names

Lists landing page campaigns with their ids and names.

Parameters

NameTypeRequiredDescription
pageIndexintegerNoPage to return, 1–1000. Defaults to 1.
pageSizeintegerNoRows per page, 1–1000. Defaults to 100.

Responses

StatusMeaning
200The rows, with paging totals alongside them.
400A required parameter is missing, or a value is out of range — pageIndex and pageSize must be 1–1000.
401Missing, expired or invalid bearer token.
curl -X GET "https://insights-dev.jirafix.net/v1/landingpage/campaign/names?pageIndex=1&pageSize=20" \
  -H "Authorization: Bearer <your-token>"
GET /v1/email/campaign/names

Lists email campaigns with their ids and names.

Parameters

NameTypeRequiredDescription
pageIndexintegerNoPage to return, 1–1000. Defaults to 1.
pageSizeintegerNoRows per page, 1–1000. Defaults to 100.

Responses

StatusMeaning
200The rows, with paging totals alongside them.
400A required parameter is missing, or a value is out of range — pageIndex and pageSize must be 1–1000.
401Missing, expired or invalid bearer token.
curl -X GET "https://insights-dev.jirafix.net/v1/email/campaign/names?pageIndex=1&pageSize=20" \
  -H "Authorization: Bearer <your-token>"
GET /v1/survey/campaign/names

Lists survey campaigns with their ids and names.

Parameters

NameTypeRequiredDescription
pageIndexintegerNoPage to return, 1–1000. Defaults to 1.
pageSizeintegerNoRows per page, 1–1000. Defaults to 100.

Responses

StatusMeaning
200The rows, with paging totals alongside them.
400A required parameter is missing, or a value is out of range — pageIndex and pageSize must be 1–1000.
401Missing, expired or invalid bearer token.
curl -X GET "https://insights-dev.jirafix.net/v1/survey/campaign/names?pageIndex=1&pageSize=20" \
  -H "Authorization: Bearer <your-token>"

How a send performed

Totals for one send — delivered, opened, clicked, bounced and so on, depending on the channel. One call, one send.

GET /v1/email/distribution/aggregated

Headline metrics for one email send.

Parameters

NameTypeRequiredDescription
idguidYesThe email send to report on, from the list above.

Responses

StatusMeaning
200The rows, with paging totals alongside them.
400A required parameter is missing, or a value is out of range — pageIndex and pageSize must be 1–1000.
401Missing, expired or invalid bearer token.
404No record matches the id you asked about on this channel. An id from another channel's list will land here.
curl -X GET "https://insights-dev.jirafix.net/v1/email/distribution/aggregated?id=3fa85f64-5717-4562-b3fc-2c963f66afa6" \
  -H "Authorization: Bearer <your-token>"
GET /v1/sms/distribution/aggregated

Headline metrics for one SMS send.

Parameters

NameTypeRequiredDescription
idguidYesThe SMS send to report on, from the list above.

Responses

StatusMeaning
200The rows, with paging totals alongside them.
400A required parameter is missing, or a value is out of range — pageIndex and pageSize must be 1–1000.
401Missing, expired or invalid bearer token.
404No record matches the id you asked about on this channel. An id from another channel's list will land here.
curl -X GET "https://insights-dev.jirafix.net/v1/sms/distribution/aggregated?id=3fa85f64-5717-4562-b3fc-2c963f66afa6" \
  -H "Authorization: Bearer <your-token>"

What happened to each recipient

Row per recipient for one send. Paged, because a large send has as many rows as it had recipients.

GET /v1/email/distribution/details

Per-recipient rows for one email send.

Parameters

NameTypeRequiredDescription
idguidYesThe email send to report on.
pageIndexintegerNoPage to return, 1–1000. Defaults to 1.
pageSizeintegerNoRows per page, 1–1000. Defaults to 100.

Responses

StatusMeaning
200The rows, with paging totals alongside them.
400A required parameter is missing, or a value is out of range — pageIndex and pageSize must be 1–1000.
401Missing, expired or invalid bearer token.
404No record matches the id you asked about on this channel. An id from another channel's list will land here.
curl -X GET "https://insights-dev.jirafix.net/v1/email/distribution/details?id=3fa85f64-5717-4562-b3fc-2c963f66afa6&pageIndex=1&pageSize=100" \
  -H "Authorization: Bearer <your-token>"
GET /v1/sms/distribution/details

Per-recipient rows for one SMS send.

Parameters

NameTypeRequiredDescription
idguidYesThe SMS send to report on.
pageIndexintegerNoPage to return, 1–1000. Defaults to 1.
pageSizeintegerNoRows per page, 1–1000. Defaults to 100.

Responses

StatusMeaning
200The rows, with paging totals alongside them.
400A required parameter is missing, or a value is out of range — pageIndex and pageSize must be 1–1000.
401Missing, expired or invalid bearer token.
404No record matches the id you asked about on this channel. An id from another channel's list will land here.
curl -X GET "https://insights-dev.jirafix.net/v1/sms/distribution/details?id=3fa85f64-5717-4562-b3fc-2c963f66afa6&pageIndex=1&pageSize=100" \
  -H "Authorization: Bearer <your-token>"

How a campaign performed

GET /v1/landingpage/campaign/aggregated

Headline metrics for one landing-page campaign, optionally over a date range.

This one takes dates; the distribution equivalents do not. Omit both to get the campaign's whole lifetime.

Parameters

NameTypeRequiredDescription
idguidYesThe campaign to report on, from the campaign list.
startDatedate-timeNoStart of the reporting window. Omit for no lower bound.
endDatedate-timeNoEnd of the reporting window. Omit for no upper bound.

Responses

StatusMeaning
200The rows, with paging totals alongside them.
400A required parameter is missing, or a value is out of range — pageIndex and pageSize must be 1–1000.
401Missing, expired or invalid bearer token.
404No record matches the id you asked about on this channel. An id from another channel's list will land here.
curl -X GET "https://insights-dev.jirafix.net/v1/landingpage/campaign/aggregated?id=3fa85f64-5717-4562-b3fc-2c963f66afa6" \
  -H "Authorization: Bearer <your-token>"

Who engaged with a campaign

Row per recipient for one campaign. The route picks the channel, and the id is a campaign id from the campaign list — a distribution id will not match.

GET /v1/landingpage/campaign/details

Per-recipient rows for one landing-page campaign.

Parameters

NameTypeRequiredDescription
idguidYesThe landing-page campaign to report on.
pageIndexintegerNoPage to return, 1–1000. Defaults to 1.
pageSizeintegerNoRows per page, 1–1000. Defaults to 100.

Responses

StatusMeaning
200The rows, with paging totals alongside them.
400A required parameter is missing, or a value is out of range — pageIndex and pageSize must be 1–1000.
401Missing, expired or invalid bearer token.
404No record matches the id you asked about on this channel. An id from another channel's list will land here.
curl -X GET "https://insights-dev.jirafix.net/v1/landingpage/campaign/details?id=3fa85f64-5717-4562-b3fc-2c963f66afa6&pageIndex=1&pageSize=100" \
  -H "Authorization: Bearer <your-token>"
GET /v1/email/campaign/details

Per-recipient rows for one email campaign.

Parameters

NameTypeRequiredDescription
idguidYesThe email campaign to report on.
pageIndexintegerNoPage to return, 1–1000. Defaults to 1.
pageSizeintegerNoRows per page, 1–1000. Defaults to 100.

Responses

StatusMeaning
200The rows, with paging totals alongside them.
400A required parameter is missing, or a value is out of range — pageIndex and pageSize must be 1–1000.
401Missing, expired or invalid bearer token.
404No record matches the id you asked about on this channel. An id from another channel's list will land here.
curl -X GET "https://insights-dev.jirafix.net/v1/email/campaign/details?id=3fa85f64-5717-4562-b3fc-2c963f66afa6&pageIndex=1&pageSize=100" \
  -H "Authorization: Bearer <your-token>"
GET /v1/survey/campaign/details

Per-recipient rows for one survey campaign.

Parameters

NameTypeRequiredDescription
idguidYesThe survey campaign to report on.
pageIndexintegerNoPage to return, 1–1000. Defaults to 1.
pageSizeintegerNoRows per page, 1–1000. Defaults to 100.

Responses

StatusMeaning
200The rows, with paging totals alongside them.
400A required parameter is missing, or a value is out of range — pageIndex and pageSize must be 1–1000.
401Missing, expired or invalid bearer token.
404No record matches the id you asked about on this channel. An id from another channel's list will land here.
curl -X GET "https://insights-dev.jirafix.net/v1/survey/campaign/details?id=3fa85f64-5717-4562-b3fc-2c963f66afa6&pageIndex=1&pageSize=100" \
  -H "Authorization: Bearer <your-token>"

Email delivery events

The raw delivery events behind an email send — delivered, open, click, bounce, dropped and so on, one row per event rather than one per recipient.

Filtering by event type

eventTypes takes a comma-separated list, e.g. open,click. eventTypeFilter decides what that list means: Include (the default) keeps only those types, Exclude drops them and keeps the rest.

GET /v1/email/webhook/events

Delivery events for one send.

Parameters

NameTypeRequiredDescription
queueIdguidYesThe send to read events for — the QueueId the Email API returned when you sent it. Omitting it is a 400.
eventTypesstringNoComma-separated event types, e.g. open,click. Omit for all.
eventTypeFilterstringNoInclude (default) or Exclude.
pageIndexintegerNoPage to return, 1–1000. Defaults to 1.
pageSizeintegerNoRows per page, 1–1000. Defaults to 100.

Responses

StatusMeaning
200The rows, with paging totals alongside them.
400A required parameter is missing, or a value is out of range — pageIndex and pageSize must be 1–1000.
401Missing, expired or invalid bearer token.
curl -X GET "https://insights-dev.jirafix.net/v1/email/webhook/events?queueId=3fa85f64-5717-4562-b3fc-2c963f66afa6&eventTypes=open,click" \
  -H "Authorization: Bearer <your-token>"

Events for SMTP-style sends

Mail sent over SMTP has no queue id to ask about, so these events are addressed by time instead: everything sent after the moment you name.

GET /v1/email/webhook/events/smtp

Delivery events for SMTP-style sends after a given time.

Parameters

NameTypeRequiredDescription
sentAfterdate-timeYesOnly events for mail sent after this moment. Required — there is no queue id to narrow by here.
eventTypesstringNoComma-separated event types. Omit for all.
eventTypeFilterstringNoInclude (default) or Exclude.
pageIndexintegerNoPage to return, 1–1000. Defaults to 1.
pageSizeintegerNoRows per page, 1–1000. Defaults to 100.

Responses

StatusMeaning
200The rows, with paging totals alongside them.
400A required parameter is missing, or a value is out of range — pageIndex and pageSize must be 1–1000.
401Missing, expired or invalid bearer token.
curl -X GET "https://insights-dev.jirafix.net/v1/email/webhook/events/smtp?sentAfter=2026-08-01T00:00:00Z" \
  -H "Authorization: Bearer <your-token>"

Find recipients by what they did

Answers questions like who was delivered but never opened. Events are rolled up per recipient, then mustHave and mustNotHave filter that set — every type in mustHave must be present, and none in mustNotHave may be.

This endpoint pages by cursor

There is no pageIndex. Read nextCursor from the response and send it back as cursor for the next page; hasMore tells you when to stop. pageSize is capped at 500 here, not 1000.

GET /v1/email/webhook/recipients/by-event-criteria

Recipients matching a combination of events they did and did not generate.

Parameters

NameTypeRequiredDescription
queueIdguidNoNarrow to one send. Omit and use sentAfter for SMTP-style mail.
smtpOnlybooleanNoRestrict to SMTP-style sends. Defaults to false.
sentAfterdate-timeNoOnly mail sent after this moment.
mustHavestringNoEvent types the recipient must all have, e.g. delivered.
mustNotHavestringNoEvent types the recipient must have none of, e.g. open,click.
pageSizeintegerNoRecipients per page, 1–500. Defaults to 100.
cursorstringNoThe nextCursor from your previous response. Omit for the first page.

Responses

StatusMeaning
200The rows, with paging totals alongside them.
400A required parameter is missing, or a value is out of range — pageIndex and pageSize must be 1–1000.
401Missing, expired or invalid bearer token.
# delivered, but never opened
curl -X GET "https://insights-dev.jirafix.net/v1/email/webhook/recipients/by-event-criteria\
?queueId=3fa85f64-5717-4562-b3fc-2c963f66afa6\
&mustHave=delivered&mustNotHave=open&pageSize=200" \
  -H "Authorization: Bearer <your-token>"
200 OK

{
  "data": [ { "email": "customer@example.com" } ],
  "nextCursor": "eyJvZmZzZXQiOjIwMH0",
  "hasMore": true
}

Revenue transactions

Your payments, one row each — amount, store, how it was taken, and the bank reference to reconcile against. These are the same records the merchant portal shows under Insights → Revenue.

Confirmed money only, by default

Only payments the bank has confirmed are returned, and test-mode payments are excluded. That is the right default for reconciliation. Pass includeUnconfirmed=true or includeTest=true to widen it.

The window is in your timezone; the timestamps come back in UTC

startDate and endDate are read in your account's own timezone, the same one the merchant portal uses — so 2026-08-01T00:00:00 means midnight where you are, not midnight UTC. Every timestamp in the response is UTC. The two ends genuinely differ; convert accordingly rather than assuming they match.

Personal data is not included

Payer names, payer phone numbers and the bank's free-text payer fields are deliberately absent from these responses. If you need to tie a payment to a customer, use your own orderId — pass it when you take the payment and match on it here.

Filtering by the E-commerce channel

channel=E commerce currently matches nothing for hosted-checkout payments. Those are recorded against the channel of the device or app that took them, so filter on that instead — or omit channel and read channel off each row.

GET /v1/revenue/transactions

A page of payments for the window you name.

Parameters

NameTypeRequiredDescription
startDatedate-timeYesStart of the window, inclusive, in your account's own timezone (not UTC) — e.g. 2026-08-01T00:00:00.
endDatedate-timeYesEnd of the window, inclusive to the minute, in your account's own timezone. No more than 90 days after startDate.
storeIdsguid[]NoRestrict to specific stores. Repeat the parameter, or pass a comma-separated list. Omit for every store on the account.
minAmountnumberNoInclusive lower bound on the transaction amount.
maxAmountnumberNoInclusive upper bound on the transaction amount.
includeUnconfirmedbooleanNoInclude payments the bank has not confirmed. Defaults to false — only confirmed money, which is what the merchant portal shows.
includeTestbooleanNoInclude test-mode payments. Defaults to false.
channelstringNoCase-insensitive substring match on how the payment was taken, e.g. Soundbox, Terminal, Business App.
orderIdstringNoCase-insensitive substring match on your own order reference.
bankReferencestringNoCase-insensitive substring match on the bank reference number.
terminalstringNoCase-insensitive substring match on the terminal identifier.
descriptionstringNoCase-insensitive substring match on the payment description.
pageIndexintegerNoPage number, 1-based, 1–1000. Defaults to 1. Split the window rather than paging deeper than that.
pageSizeintegerNoRecords per page, 1–100. Defaults to 50. Lower than the 1000 the campaign endpoints allow — this is a much heavier query.

Responses

StatusMeaning
200The requested page of transactions, with paging totals alongside them.
400The window is missing, inverted, longer than 90 days, or pageSize is above 100. The message says which.
401Missing, expired or invalid bearer token.
curl -X GET "https://insights-dev.jirafix.net/v1/revenue/transactions?startDate=2026-08-01T00:00:00Z&endDate=2026-08-20T23:59:59Z&pageSize=50" \
  -H "Authorization: Bearer <your-token>"

Revenue summary

The headline figures for a period: what you took, across how many payments, at what average — each with its movement against the window of the same length immediately before it.

GET /v1/revenue/summary

Totals and period-over-period movement for the window you name.

Parameters

NameTypeRequiredDescription
startDatedate-timeYesStart of the window, inclusive, in your account's own timezone (not UTC) — e.g. 2026-08-01T00:00:00.
endDatedate-timeYesEnd of the window, inclusive to the minute, in your account's own timezone. No more than 90 days after startDate.
storeIdsguid[]NoRestrict to specific stores. Repeat the parameter, or pass a comma-separated list. Omit for every store on the account.
minAmountnumberNoInclusive lower bound on the transaction amount.
maxAmountnumberNoInclusive upper bound on the transaction amount.
includeUnconfirmedbooleanNoInclude payments the bank has not confirmed. Defaults to false — only confirmed money, which is what the merchant portal shows.
includeTestbooleanNoInclude test-mode payments. Defaults to false.

Responses

StatusMeaning
200The figures for the requested window.
400The window is missing, inverted, or longer than 90 days. The message says which.
401Missing, expired or invalid bearer token.
curl -X GET "https://insights-dev.jirafix.net/v1/revenue/summary?startDate=2026-08-01T00:00:00Z&endDate=2026-08-20T23:59:59Z" \
  -H "Authorization: Bearer <your-token>"

Revenue trend

Daily revenue totals across the window, oldest first — for charting.

Quiet days are absent, not zero

A day with no revenue produces no point at all. Plot against the window you asked for rather than against the number of points you got back, or a quiet stretch will compress your x-axis.

GET /v1/revenue/trend

Daily revenue totals for the window you name.

Parameters

NameTypeRequiredDescription
startDatedate-timeYesStart of the window, inclusive, in your account's own timezone (not UTC) — e.g. 2026-08-01T00:00:00.
endDatedate-timeYesEnd of the window, inclusive to the minute, in your account's own timezone. No more than 90 days after startDate.
storeIdsguid[]NoRestrict to specific stores. Repeat the parameter, or pass a comma-separated list. Omit for every store on the account.
minAmountnumberNoInclusive lower bound on the transaction amount.
maxAmountnumberNoInclusive upper bound on the transaction amount.
includeUnconfirmedbooleanNoInclude payments the bank has not confirmed. Defaults to false — only confirmed money, which is what the merchant portal shows.
includeTestbooleanNoInclude test-mode payments. Defaults to false.

Responses

StatusMeaning
200The figures for the requested window.
400The window is missing, inverted, or longer than 90 days. The message says which.
401Missing, expired or invalid bearer token.
curl -X GET "https://insights-dev.jirafix.net/v1/revenue/trend?startDate=2026-08-01T00:00:00Z&endDate=2026-08-20T23:59:59Z" \
  -H "Authorization: Bearer <your-token>"

Errors

StatusWhat it meansWhat to do
200The query ran.An empty data array is a valid answer — it means no rows matched.
400A required parameter is missing, or a value is out of range.Check id/queueId is present and that paging values are within bounds.
401The token is missing, expired or invalid.Fetch a new token and retry once.
404Nothing matches that id on this channel.Confirm the id came from the matching list endpoint — campaign and distribution ids are not interchangeable.
An id from the wrong list is the usual cause of a 404

A campaign id sent to a distribution endpoint — or an email id sent to the SMS route — will not resolve. Both come back as 404, not as a message explaining the mix-up.

Limits

LimitValue
pageIndex1–1000
pageSize (most endpoints)1–1000, default 100
pageSize (recipients by behaviour)1–500, default 100