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

# Reporter core concepts

> The Reporter model in one place: templates, data sources, reports, deadlines, the four report states, and the tenant boundary that separates them.

Reporter has a small model. You upload a **template** that describes a document. An operator configures the **data sources** Reporter may read. You request a **report** against a template, and Reporter renders an artifact you download. A **deadline** tracks when a report is due and whether someone delivered it.

This page defines each noun and the rules that connect them.

## The model at a glance

***

| Concept     | Definition                                                                             |
| ----------- | -------------------------------------------------------------------------------------- |
| Template    | A plain-text document definition, uploaded as a file, that declares one output format. |
| Data source | A read-only database that an operator registers through configuration.                 |
| Report      | One rendering of one template, under the filters you asked for.                        |
| Artifact    | The file a finished report produces, held in object storage.                           |
| Filter      | A per-field condition that narrows the rows a report reads.                            |
| Deadline    | A due date and a recurrence rule, optionally bound to a template.                      |
| Tenant      | The isolation boundary. Every operation resolves exactly one.                          |

## Templates

***

A template is a plain-text `.tpl` file that you upload as `multipart/form-data`, together with the output format it produces and a short description. Reporter keeps the file in object storage and its metadata in MongoDB. The template language is Pongo2, so a template mixes literal document text with variables, loops, conditionals, filters, and aggregation tags.

One template declares one output format: `PDF`, `HTML`, `XML`, `TXT`, or `CSV`. PDF renders as HTML first and then converts through a headless-browser worker pool.

A template addresses data by `configName`, the stable name of a data source, and by table: `{{ midaz_onboarding.accounts }}`. When more than one schema is in play, qualify it as `{{ midaz_onboarding:public.accounts }}`.

At upload, Reporter reads the template text and derives the fields it touches, per data source and per table. It then checks every referenced table and field against the live schema of that data source. A data source that is unreachable produces a warning rather than a rejection, so a template still uploads while a database is down.

Read [Template reference](/en/reporter/template-reference) for the tags, filters, and expressions the language offers.

## Data sources

***

A data source is a database Reporter reads, registered entirely through environment configuration. Reporter connects to PostgreSQL and MongoDB. Access is read-only by construction: the extraction path issues `SELECT` statements and MongoDB finds, and no write path to a data source exists.

`DATASOURCE_<NAME>_CONFIG_NAME` is the variable that makes a data source exist. Its value is the `configName` that templates and filters use, and it stays stable while hosts and credentials change around it. The rest of the block supplies the connection itself.

The API surface over data sources is read-only too. You can list the configured sources and get one by identifier, which is how you confirm that a deployment sees the source a template expects. There is no create, update, or delete operation, because the environment owns that decision.

Read [Connecting Reporter to Midaz](/en/reporter/connecting-reporter-to-midaz) for a worked configuration.

## Reports

***

A report request names a template and, optionally, the filters that narrow the data behind it. Filters nest three levels — data source, then table, then field — and each field carries one condition:

```json theme={null}
{
  "templateId": "0198c0f6-6d4d-7a34-a9ba-2c2b3ad2f1a0",
  "filters": {
    "midaz_onboarding": {
      "accounts": {
        "status": { "in": ["ACTIVE"] },
        "type": { "nin": ["internal"] }
      }
    }
  }
}
```

Eight operators exist: `eq`, `gt`, `gte`, `lt`, `lte`, `between`, `in`, and `nin`.

A report keeps its own copy of the output format and description that the template carried when the report was created. That snapshot is why an artifact stays downloadable in its original shape after the template moves on.

Reports are create-and-retain. Four operations exist: create one, get it by identifier, list them, and download the artifact of a finished one. A report and its artifact remain in place once created; retention is a lifecycle policy on the object-storage bucket, set by whoever operates the deployment.

### The four report states

Creation is synchronous only up to the point where the work is queued. `POST` answers `201 Created` with a report already in `Processing`, and a worker takes it from there.

| State        | Meaning                                                                                                                                |
| ------------ | -------------------------------------------------------------------------------------------------------------------------------------- |
| `Processing` | Accepted and queued. The worker has not finished.                                                                                      |
| `Finished`   | Every data section succeeded and the artifact is stored.                                                                               |
| `Partial`    | Some data sections failed. The report records which ones, by section, so you can fix those data sources and generate the report again. |
| `Error`      | Every attempted section failed, or the request never reached the worker.                                                               |

`Processing` is the only entry state, and nothing returns to it once the worker settles the report. A queue can deliver the same command twice, so the worker reads the report before it starts a run: one that already settled as `Finished` or `Error` is left as it is, rather than generated again.

The download operation serves the artifact once a report is `Finished`. Poll `GET /v1/reports/{id}` until the state settles, or subscribe to the terminal events Reporter emits and skip the polling.

## Deadlines

***

A deadline models an obligation: a due date, a recurrence rule, and optionally the template that satisfies it. Its `type` is `regulatory` or `custom`. Its `frequency` is `once`, `daily`, `weekly`, `monthly`, `semiannual`, or `annual`, and the semiannual and annual rules also carry the months they fall in.

Status is derived, never stored. A deadline is `delivered` once someone marks it so, `overdue` once its due date passes undelivered, and `pending` otherwise. A recurring deadline rolls forward on the first read after its due date passes, and only when it was marked delivered. That roll-forward clears the delivery mark, so the record returns to `pending` for the next occurrence and one record carries the whole series.

Notification is pull-based. A single operation returns the deadlines inside their alert window, ranked overdue first, then warning, then informational. Reporter sends no mail and calls no endpoint of yours.

Read [Managing deadlines](/en/reporter/managing-deadlines) for the full lifecycle.

## Tenants

***

The tenant is the isolation boundary in Reporter. Reporter resolves it from the authenticated request itself — the bearer token that authorizes the call carries the tenant in its `tenantId` claim. No API operation takes a tenant from a request header, and no client-supplied value can widen the scope of a call.

Isolation runs the whole depth of the stack. Each tenant gets its own metadata database, its own message-broker virtual host, its own connection pools, and its own event outbox. Resolution is fail-closed: a request whose tenant cannot be resolved is rejected, and nothing falls back to a shared pool.

Single-tenant operation is the default and needs no tenant configuration at all. See [Multi-tenancy](/en/multi-tenancy) for the platform-wide model.

## Next steps

***

<CardGroup cols={2}>
  <Card title="Architecture" icon="sitemap" href="/en/reporter/reporter-architecture">
    One binary, two surfaces, and the queue between them.
  </Card>

  <Card title="Quick start" icon="rocket" href="/en/reporter/reporter-quick-start">
    Upload a template and generate your first report.
  </Card>

  <Card title="Template reference" icon="code" href="/en/reporter/template-reference">
    The tags, filters, and expressions available to a template.
  </Card>

  <Card title="Managing deadlines" icon="calendar" href="/en/reporter/managing-deadlines">
    Create, track, and deliver a reporting obligation.
  </Card>
</CardGroup>
