The model at a glance
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 for the tags, filters, and expressions the language offers.
Data sources
A data source is a PostgreSQL or MongoDB connection stored in Reporter’s registry. The API creates and manages registry entries. A single-tenant deployment can also seed them from
DATASOURCE_* variables at startup. Data extraction remains read-only by construction: Reporter issues SELECT statements and MongoDB finds, and it has no write path into the source database.
Each entry has two identifiers. The dataSourceId is the UUID that registry operations use. The configName is the stable name that templates and filters use, so keep it stable while hosts and credentials change. Reporter encrypts passwords at rest with DATASOURCE_CRED_ENC_KEY and never returns them.
The registry exposes seven operations: list, create, get, partially update, soft-delete, inspect the live schema, and test the connection. Reporter refuses deletion while a live template still references the source.
Read 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:
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 at creation time. 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 until the work reaches the queue. ThePOST operation answers 201 Created with a report already in Processing, and a worker takes it from there.
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. The worker skips a report that already settled as Finished or Error, and does not generate it 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.
Reporter derives status and never stores it. 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. It rolls forward only when it carries the delivery mark. 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 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. Reporter rejects a request when it cannot resolve the tenant, and nothing falls back to a shared pool.
Single-tenant operation is the default and needs no tenant configuration at all. See Multi-tenancy for the platform-wide model.
Next steps
Architecture
One binary, two surfaces, and the queue between them.
Quick start
Upload a template and generate your first report.
Template reference
The tags, filters, and expressions available to a template.
Managing deadlines
Create, track, and deliver a reporting obligation.

