---
title: "Automate reports — daily e-mails and pulling data over the API"
description: "Get yesterday's numbers without opening the console — schedule a saved report by e-mail, pull it over the analytics REST API from a script, and forward it to a chat or spreadsheet."
type: "howto"
audience: [network-manager]
keywords: [automate reports, daily report, email report, api report, telegram]
ui_path: "Account → Analytics → Saved reports → schedule"
---

Fetch the complete documentation index at: https://epom.com/ad-server/docs/llms.txt. Use this file to discover all available pages before exploring further. Append .md to any documentation page URL to get its markdown version.

# Automate reports — daily e-mails and pulling data over the API

Two ways to get numbers out of Epom on a schedule: let Epom **e-mail** a saved report, or have
your own script **pull** it over the analytics API and send it wherever you need — a chat, a
spreadsheet, a billing system.

## Who this is for

Anyone who can run reports. The API needs your API key or your password-based hash; both are
described in the [API overview](https://epom.com/ad-server/docs/api.md).

## Prerequisites

- Access to **Analytics**, and a report you can build there — see [Run a report](https://epom.com/ad-server/docs/guides/analytics/run-report.md).
- **For e-mail:** at least one recipient address on the saved report, and outbound mail configured
  by Epom for your network.
- **For the API:** your login and password (for the signed URL), or an API key. Calling with an API
  key needs the *API Key Access* permission on your role — no stock role has it, so ask your
  network administrator; see the [API overview](https://epom.com/ad-server/docs/api.md).

## Steps

Pick one of the two options below — or both: e-mail for people, the API for scripts.

### Option 1 — a daily e-mail (no code)

1. **Account → Analytics**, build the report: type, **Yesterday** as the date range, group-by and
   columns.
2. **Save** it as a template.
3. In **Saved reports**, click the clock icon, pick the days (every weekday, or days of the
   month), an **hour in UTC** and a format — CSV, XLSX, PDF, HTML or JSON — and click **Add**.
4. Add recipients under **Report recipients**.

The schedule is checked once an hour; the report runs with its saved range relative to the run
day, so **Yesterday** always means the day before the e-mail. Details and every option:
[Save, reuse and schedule reports](https://epom.com/ad-server/docs/guides/analytics/saved-and-scheduled.md).

### Option 2 — pull yesterday’s data from a script

The analytics API runs the same reports as the console. One call returns yesterday's figures
grouped by site and country as CSV:

```bash
TS=$(date +%s000)                                   # Unix time in milliseconds
HASH=$(printf '%s%s' "$(printf '%s' "$PASSWORD" | md5sum | cut -d' ' -f1)" "$TS" | md5sum | cut -d' ' -f1)
curl -o yesterday.csv \
  "https://<your-network-domain>/rest-api/analytics/CSV/$LOGIN/$HASH/$TS.do?range=YESTERDAY&groupBy=SITE&groupBy=COUNTRY"
```

Or with an API key, as JSON:

```bash
curl -H "X-Api-Key: $APIKEY" "https://<your-network-domain>/rest-api/analytics/JSON.do?range=YESTERDAY&groupBy=CAMPAIGN&groupRange=DAY&jsonKeys=id"
```

`jsonKeys=id` names each JSON field by its column id (`impressions`, `sumGross`) instead of the
column's display name in your interface language, so the script reads the same keys whoever runs it
and no two columns share one — see [JSON output](https://epom.com/ad-server/docs/api/analytics-api.md#json-output).

Useful parameters (full list in the [Analytics reports via API](https://epom.com/ad-server/docs/api/analytics-api.md)):

| Parameter | For |
|---|---|
| `range=YESTERDAY`, `LAST_7_DAYS`, `LAST_MONTH` … or `CUSTOM` with `customFrom` / `customTo` | The period |
| `groupBy` (repeatable) | Rows per site, campaign, country … |
| `groupRange=DAY` / `HOUR` | One row per day / hour |
| `statisticType` | Leave out for the General report; `HADOOP` for Advanced |
| `limit`, `offset` | Paging; without `limit` you get up to your network's records-per-request limit |

A saved report can be fetched by its definition too: `GET /rest-api/saved-reports/{id}.do`
returns its `params` under exactly these names.

> **Note — run it after midnight in the reporting time zone.** "Yesterday" is the day before in
> the ad server's reporting time zone (General) or in the report's own time zone (Advanced). A
> script run at 00:05 gets a complete yesterday from General; late-arriving data can still move
> it slightly for a few hours. See
> [Which time zone do reports use?](https://epom.com/ad-server/docs/concepts/analytics-pipelines-explained.md#which-time-zone-do-reports-use).

#### Steps for a scripted pull

1. Check your quota once: `GET /rest-api/network/settings.do` returns `analyticsApi` with
   `dailyRequestLimit`, `requestsUsedToday` and `recordsPerRequestLimit`.
2. Build the report in the console first, so you know which `groupBy`, `range` and
   `statisticType` give the rows you want — or save it and read its `params` from
   `GET /rest-api/saved-reports/{id}.do`.
3. Put one of the calls above in a scheduled job, timed after midnight in the reporting time zone.
4. Check the HTTP status before using the body: `200` is a report; `400`, `401`, `403` and `429`
   keep a JSON body with `success:false` and the reason.

## Forward it to a chat, a sheet or a bot

Epom does not post to messengers itself. Put the call above in a scheduled job (cron, a CI
scheduler, a cloud function), turn the JSON or CSV into a message, and send it with the
destination's own API — Telegram's `sendMessage` / `sendDocument`, a Slack incoming webhook, a
Google Sheets append. The analytics call is the only Epom part.

## Limits to plan for

- Each user has a **daily number of report requests**; once used up, calls answer `429` until
  the next day. `GET /rest-api/network/settings.do` shows `dailyRequestLimit` and
  `requestsUsedToday` under `analyticsApi`.
- A `limit` above the records-per-request limit is a `400`. Page with `offset` instead.
- Pull one report grouped by the dimension you need — not one call per campaign.
- Advanced reports only cover the short window of days the event logs are kept for; daily
  jobs over long periods belong on the General report.

## Corner cases and gotchas

> **Corner case:** a scheduled report with **no recipients is rendered on time and sent to
> nobody**. The owner is not added automatically — add your own address if you want a copy.

> **Corner case:** a report scheduled on day **29, 30 or 31** of the month is skipped in months
> that have no such day. To get a month-end report every month, schedule day **1** with a
> **Last month** range instead.

> **Corner case:** nothing is sent while the account that owns the saved report — or its parent
> account — is inactive. The schedule stays in place and resumes when the account is re-activated.

> **Corner case:** the e-mailed file is cut at your network's row limit for its format (CSV, XLSX,
> PDF, HTML and JSON each have their own). If the file looks truncated, group more coarsely or pull
> it over the API with `limit` and `offset`.

> **Corner case:** the e-mail runs the report **as its owner** — with the owner's permissions, in
> the owner's interface language and with the columns saved in the report — whoever the recipients
> are.

> **Corner case:** a signed (login / hash / timestamp) call from a deactivated account is refused
> with `401`, like every other REST call — a script under a departed colleague's login stops
> working the day the account is switched off. Use a dedicated reporting user.

## Per-role notes

- **Network manager, publisher, advertiser** — identical. Both the e-mail and the API return only
  the entities and columns your role may see in the console; shared inventory and campaigns show
  the names your share allows.
- **Saved reports are private to each login** — a colleague cannot schedule yours; add them as a
  recipient instead.
- **Custom-role users** — an API key needs *API Key Access*; a report type or column the role lacks
  answers `403` naming the missing reporting permission.

## Related

- [Save, reuse and schedule reports](https://epom.com/ad-server/docs/guides/analytics/saved-and-scheduled.md)
- [Analytics reports via API](https://epom.com/ad-server/docs/api/analytics-api.md)
- [API overview and authentication](https://epom.com/ad-server/docs/api.md)
- [How Epom computes your numbers](https://epom.com/ad-server/docs/concepts/analytics-pipelines-explained.md)