> ## Documentation Index
> Fetch the complete documentation index at: https://docs.kaireonai.com/llms.txt
> Use this file to discover all available pages before exploring further.

# First scheduled report

> End-to-end tutorial: create a template, preview it, schedule it, and receive the output.

This tutorial walks the Reports flow end-to-end. It assumes you have:

* A KaireonAI tenant with some interaction history (the retail rewards
  dataset works fine — see [Sample data](/get-started/sample-data)).
* At least one notification provider configured under
  [Settings → Integrations → Notifications](/operations-reporting/notifications).
* An AI provider configured under
  [Settings → AI Configuration](/ai-ml/ai-configuration) if you want
  LLM narration.

## 1. Create a template

1. Navigate to **Dashboards → Reports**.
2. Click **New Report**.
3. Under **Details**, give it a name: `Weekly digest`.
4. Under the **Compose** tab, leave the default `Offer performance (7
   days)` source. Click **Add source** and pick `Channel effectiveness`.
5. Under **Format & narrative**, tick **PDF** and **CSV**. Leave
   **Enable AI narrative** on. Add a prompt addendum like `Flag any
   offer with >15% week-over-week drop.` (optional).
6. Click **Save**. The editor navigates to the template-edit page with
   a populated preview pane.

## 2. Preview

The preview pane on the right renders the executive summary (if the
narrator is enabled) and a row-count per section. Preview refreshes
automatically 600ms after every change to the form.

## 3. Schedule delivery

<Note>
  **Creating a schedule does not automatically fire the report.** Schedules
  depend on an external scheduler (AWS EventBridge) hitting
  `/api/cron/tick` on a cadence. During pilot / initial deployment this is
  usually not wired — see [EventBridge Setup](/self-host/deploy/eventbridge-setup)
  for the optional wiring path.

  Until the cron is wired, use **Run Now** (next step) whenever you want a
  scheduled report delivered. Run Now works unconditionally and does not
  depend on any scheduler being in place.
</Note>

1. Still on the template-edit page, switch to the **Schedule** tab.
2. Tick the notification destinations you want to deliver to.
3. Set a **Schedule name**: `Daily 8am UTC`.
4. Leave **Timezone** as **UTC**.
5. Set **Cron expression** to `0 8 * * *`.
6. Click **Add schedule**. The schedule appears in the list below with
   its next run time.

The `nextRunAt` timestamp is computed and stored but only acts as a
trigger when a scheduler invokes `/api/cron/tick`.

## 4. Run it now (works without EventBridge)

This is the recommended path during pilot — it bypasses the scheduler
entirely and delivers the report immediately.

1. Back at **Dashboards → Reports**, click **Run now** on the template's
   row.
2. A toast announces the run's ID.

Check your destination:

* **Ops email**: arrives with PDF + CSV attachments; body contains the
  executive summary and key takeaways.
* **Slack/Teams**: message with the summary, key takeaways bullets,
  and a deep link back to `/api/v1/reports/runs/[id]`.
* **Webhook**: POST body includes artifact base64 inline.

Equivalent API call:

```bash theme={null}
curl -X POST "$PLATFORM_URL/api/v1/reports/templates/$TEMPLATE_ID/run-now" \
  -H "X-API-Key: $KEY" -H "X-Tenant-Id: $TENANT"
```

## 5. Optional — verify cron wiring

Skip this step during pilot unless you've already followed
[EventBridge Setup](/self-host/deploy/eventbridge-setup).

Once the cron is wired and `CRON_TOKEN` is set on the service, you can
simulate a scheduled run by invoking the tick manually:

```bash theme={null}
curl -X POST "$PLATFORM_URL/api/cron/tick" \
  -H "x-cron-token: $CRON_TOKEN"
```

You should see a JSON response containing `reportsEvaluated`,
`reportsRan`, and (for this tenant) an updated `lastRunAt` on the
schedule — assuming the schedule's `nextRunAt` has already elapsed.

## 6. Browse run history

Each run is persisted as a row in the report-runs table. You can fetch them:

```bash theme={null}
curl "$PLATFORM_URL/api/v1/reports/runs?templateId=$TEMPLATE_ID" \
  -H "X-API-Key: $KEY" -H "X-Tenant-Id: $TENANT"
```

And download a specific artifact:

```bash theme={null}
curl -O "$PLATFORM_URL/api/v1/reports/runs/$RUN_ID/artifacts/pdf" \
  -H "X-API-Key: $KEY" -H "X-Tenant-Id: $TENANT"
```

## Troubleshooting

* **Empty executive summary** — either the AI provider isn't configured
  or the narrator couldn't parse the model's response. The run still
  produces artifacts; the narrative section is simply empty.
* **Schedule was created but never fires** — expected during pilot. The
  cron must be wired; until then use **Run Now**. See
  [EventBridge Setup](/self-host/deploy/eventbridge-setup).
* **Schedule stuck at `lastStatus: "failed"`** — check the
  `errorMessage` column. Common causes: invalid cron, deleted template
  referenced by schedule, or a data source querying a table the tenant
  lacks.
* **Destination delivery failures** — visit Settings → Integrations →
  Notifications and use each provider's Test Connection button.
