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

# Reports & TraddalQL

> Explore shipments, billing and payments with a query language you can save and share.

Reports live at **Reports** in the sidebar. Open a default report, or start a
**New exploration**, edit the query, press **Run** (⌘/Ctrl + Enter) and save
what you find. Saved reports can be personal or shared with the whole team.

## The query language

TraddalQL is a small, ShopifyQL-shaped language. Every query starts with the
data to report on and what to measure:

```sql theme={null}
FROM shipments
SHOW shipments, payment_collected
GROUP BY destination_country
DURING last_30_days
ORDER BY shipments DESC
LIMIT 20
```

| Clause            | What it does                                                                                   | Example                                                               |
| ----------------- | ---------------------------------------------------------------------------------------------- | --------------------------------------------------------------------- |
| `FROM`            | Choose the schema (table)                                                                      | `FROM charges`                                                        |
| `SHOW`            | Metrics to measure (`AS` renames a column)                                                     | `SHOW amount AS revenue, margin`                                      |
| `GROUP BY`        | Dimensions to slice by                                                                         | `GROUP BY customer, currency`                                         |
| `WHERE`           | Filter rows before aggregation                                                                 | `WHERE status != 'cancelled' AND destination_country IN ('US', 'CA')` |
| `TIMESERIES`      | One row per `hour`, `day`, `week`, `month`, `quarter` or `year`, gaps filled with zero         | `TIMESERIES week`                                                     |
| `DATE BY`         | Which date the time clauses use                                                                | `DATE BY paid_at`                                                     |
| `SINCE` / `UNTIL` | Time window (`'2026-01-01'`, `today`, `yesterday`, `-30d`, `-12m`, `-1y`, `startOfMonth(-1m)`) | `SINCE -90d UNTIL today`                                              |
| `DURING`          | A preset window                                                                                | `DURING last_month`                                                   |
| `COMPARE TO`      | Compare against `previous_period` or `previous_year`                                           | `COMPARE TO previous_period`                                          |
| `WITH`            | `TOTALS` adds a totals row; `PERCENT_CHANGE` shows change vs the comparison                    | `WITH TOTALS, PERCENT_CHANGE`                                         |
| `ORDER BY`        | Sort by a shown metric or grouped dimension                                                    | `ORDER BY amount DESC`                                                |
| `LIMIT`           | Cap rows (default 1000, max 5000)                                                              | `LIMIT 50`                                                            |
| `VISUALIZE`       | Draw a metric (`TYPE line`, `bar`, `area` or `table`)                                          | `VISUALIZE amount TYPE bar`                                           |

`WHERE` supports `=`, `!=`, `<`, `<=`, `>`, `>=`, `IN (...)`, `NOT IN (...)`,
`IS NULL`, `IS NOT NULL`, `CONTAINS 'text'`, `STARTS WITH 'text'`, combined
with `AND`, `OR`, `NOT` and parentheses. Text comparisons are
case-insensitive. Comments start with `--`.

`DURING` presets: `today`, `yesterday`, `this_week`, `last_week`,
`this_month`, `last_month`, `this_quarter`, `last_quarter`, `this_year`,
`last_year`, `last_7_days`, `last_30_days`, `last_90_days`, `last_365_days`,
`all_time`. A `TIMESERIES` without a window defaults to the last 30 days.

## Schemas

| Schema      | One row per           | Highlights                                                                                                                                                           |
| ----------- | --------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `shipments` | shipment              | `shipments`, `cancelled_shipments`, `shipping_cost`, `payment_collected`, `customers`; by `destination_country`, `incoterm`, `customer`, `status`, `source`          |
| `parcels`   | parcel                | `parcels`, `total_weight`, `actual_weight`, `dispatched_parcels`, `delivered_parcels`, `average_transit_days`; by `carrier`, `packaging_type`, `destination_country` |
| `charges`   | billing ledger line   | `amount`, `cost`, `margin`, `invoiced_amount`, `uninvoiced_amount`; by `kind`, `product_code`, `zone_code`, `customer`, `currency`                                   |
| `invoices`  | invoice               | `total`, `tax`, `amount_paid`, `outstanding`, `overdue`, `average_days_to_pay`; by `status`, `customer`, `currency`                                                  |
| `payments`  | receiver payment link | `payment_links`, `paid_links`, `conversion_rate`, `amount_paid`, `fees`, `average_hours_to_pay`                                                                      |
| `duties`    | duty assessment       | `duty`, `taxes`, `fees`, `total`; by `kind`, `source`, `destination_country`                                                                                         |
| `events`    | parcel event          | `events`, `parcels`; by `event`, `canonical_type`, `source`, `location_country`                                                                                      |

The editor's suggestions list every metric and dimension with a description,
and the **Controls** rail edits the same query text — pick metrics,
dimensions, a time window and a chart type without typing.

Money metrics are summed in the row's own currency: group by the schema's
`currency` dimension when you bill in more than one.

## Limits

* Reports run inside the organisation's row-level security and never see
  another tenant's data.
* A query runs for at most 15 seconds and returns at most 5,000 rows; a
  `TIMESERIES` may produce at most 2,000 buckets.
* Report runs are limited per organisation (60 per minute) to keep dashboards
  responsive for everyone.
