Skip to content

Report template

A monthly summary report: key figures, a table and notes. Uses the API's header and footer options so every page gets a running title and “Page X of Y”.

Loading preview…

The actual PDF from the API. Open it full size

Render with your data

Built in as report. Send your JSON, get the PDF. The data shown is invented sample data.

curl https://api.pagenull.dev/v1/templates/report/render \
  -H "Authorization: Bearer $PAGENULL_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "data": {
    "title": "Monthly report",
    "period": "October 2026",
    "client": "Example Ltd",
    "kpis": [
      {
        "label": "Sessions",
        "value": "18,240"
      },
      {
        "label": "Signups",
        "value": "412"
      },
      {
        "label": "Conversion",
        "value": "2.26%"
      }
    ],
    "rows": [
      {
        "channel": "Organic search",
        "sessions": "9,880",
        "signups": "241",
        "rate": "2.44%"
      },
      {
        "channel": "Paid social",
        "sessions": "5,120",
        "signups": "97",
        "rate": "1.89%"
      },
      {
        "channel": "Referral",
        "sessions": "2,060",
        "signups": "58",
        "rate": "2.82%"
      },
      {
        "channel": "Direct",
        "sessions": "1,180",
        "signups": "16",
        "rate": "1.36%"
      }
    ],
    "notes": [
      "All figures are sample data for the template preview.",
      "The header and footer are passed as separate options, so they repeat on every page with the page number."
    ]
  }
}' \
  -o report.pdf

HTML source

Copy it into the dashboard to make your own version.

report.html
<!doctype html><html><head><meta charset="utf-8"><title>{{title}}</title><style>
  *{box-sizing:border-box}
  html{-webkit-print-color-adjust:exact;print-color-adjust:exact}
  body{margin:0;font-family:"Helvetica Neue", Helvetica, Arial, "Liberation Sans", "DejaVu Sans", sans-serif;color:#16181d;font-size:14px;line-height:1.5;text-rendering:geometricPrecision}
  table{width:100%;border-collapse:collapse}
  th{text-align:left;font-weight:700;color:#3d424a;font-size:12px;padding:0 0 8px;border-bottom:1.5px solid #16181d}
  td{padding:11px 0;border-bottom:1px solid #d9dbd6;vertical-align:top}
  tr{break-inside:avoid}
  .num{text-align:right;font-variant-numeric:tabular-nums;white-space:nowrap}
  .muted{color:#4f545c}
  .label{font-size:12px;font-weight:700;color:#4f545c;margin-bottom:4px}

  h1{font-size:34px;line-height:1.1;margin:0 0 6px;letter-spacing:-.03em}
  .sub{font-size:15px;color:#4f545c}
  h2{font-size:18px;margin:36px 0 12px;letter-spacing:-.01em;break-after:avoid}
  .kpis{display:grid;grid-template-columns:repeat(3,1fr);gap:14px;margin:30px 0 0}
  .kpi{border:1px solid #c9ccc5;border-radius:6px;padding:14px 16px}
  .kpi span{font-size:13px;font-weight:700;color:#4f545c}
  .kpi b{display:block;font-size:28px;letter-spacing:-.02em;margin-top:4px}
  p{max-width:64ch;margin:0 0 10px}
</style></head><body>
<h1>{{title}}</h1><div class="sub">{{period}}, prepared for {{client}}</div>
<div class="kpis">{{#kpis}}<div class="kpi"><span>{{label}}</span><b>{{value}}</b></div>{{/kpis}}</div>
<h2>Breakdown by channel</h2>
<table><thead><tr><th>Channel</th><th class="num">Sessions</th><th class="num">Signups</th><th class="num">Rate</th></tr></thead>
<tbody>{{#rows}}<tr><td>{{channel}}</td><td class="num">{{sessions}}</td><td class="num">{{signups}}</td><td class="num">{{rate}}</td></tr>{{/rows}}</tbody></table>
<h2>Notes</h2>{{#notes}}<p>{{.}}</p>{{/notes}}
</body></html>