01
Write it, or ask for it.
Supports PostgreSQL · MySQL · MariaDB · SQL Server · SQLite, with TLS and SSH tunnels.

SELECT region, COUNT(*) AS orders, ROUND(SUM(total), 2) AS revenue FROM orders WHERE created_at >= {{yesterday}} GROUP BY region ORDER BY revenue DESC
Good morning! Here are yesterday's sales.
| region | orders | revenue |
|---|---|---|
| East | 6 | 548.35 |
| West | 5 | 500.24 |
| South | 8 | 495.87 |
| Central | 5 | 382.59 |
| North | 1 | 85.10 |
21 seconds, recorded on a real Rowbird
How it works
01
Supports PostgreSQL · MySQL · MariaDB · SQL Server · SQLite, with TLS and SSH tunnels.


02
0 7 * * 1-5 at 07:00, Monday through Friday
03

Destinations
| Destination | Inline | Files | Link |
|---|---|---|---|
| SMTP, HTML table plus plain text | Supported | Supported | Supported |
| Bot token or incoming webhook | Supported | Supported | Supported |
| Bots, files up to 50 MB | Supported | Supported | Supported |
| Webhooks, Markdown tables | Supported | Supported | Supported |
| JSON, signed with HMAC-SHA256 | Supported | Not supported | Supported |
| AWS, MinIO, R2, B2, Wasabi, Spaces | Not supported | Supported | Not supported |
| Push monitor, up or down per run | Supported | Not supported | Not supported |
Alerts
has_rowsrow_count > 50revenue < 1000changedConfig as code
apiVersion: rowbird.dev/v1 kind: Report metadata: name: daily-sales spec: query: { ref: sales-by-region } schedule: { cron: "0 7 * * 1-5", timezone: America/Sao_Paulo } condition: { match: all, rules: [{ type: has_rows }] } deliveries: - channel: sales-slack mode: attachment formats: [xlsx, pdf] - channel: finance-email mode: link link: { expiresIn: 7d, requireLogin: true }
Install
Open localhost:8080 and create the first admin.
Sample data, a fake inbox and four reports, ready to run.