Introduction

The ReportForge API accepts CSV or JSON data and returns a fully styled, self-contained HTML document. Every response includes embedded CSS and is ready to open in a browser and print to PDF.

Base URL: https://reportforge-api.vercel.app

curl
# Minimal example — no API key required on free tier
curl -X POST https://reportforge-api.vercel.app/api/csv-to-report \
  -H "Content-Type: application/json" \
  -d '{
    "csv": "item,amount\nWidgets,1250.00\nGadgets,890.50",
    "template": "sales-summary",
    "title": "Q1 2026 Sales"
  }'

# Response
{
  "html": "<!DOCTYPE html>...",
  "meta": {
    "template": "sales-summary",
    "rowCount": 2,
    "columns": ["item", "amount"],
    "generatedAt": "2026-02-28T12:00:00.000Z"
  }
}

Authentication

The free tier requires no authentication. Paid plans use an API key passed in the X-API-Key header.

curl
curl -X POST https://reportforge-api.vercel.app/api/csv-to-report \
  -H "Content-Type: application/json" \
  -H "X-API-Key: rf_your_api_key_here" \
  -d '{ "csv": "...", "template": "invoice" }'
Header Value Required
X-API-Key Your API key, prefixed rf_ Starter and Business tiers only
Content-Type application/json Required for POST endpoints
API keys are issued after subscribing. They appear in your Stripe payment confirmation email.

Rate Limits & Tiers

Limits are applied per API key on paid plans, or per IP address on the free tier. The daily counter resets at midnight UTC.

Tier Price Reports / Day Max Input API Key
Free $0 50 100 KB Not required
Business $49 / mo 5,000 10 MB Required (rf_...) Subscribe →
When the daily limit is hit the API returns 429 RATE_LIMITED. Upgrade your plan or wait for the counter to reset at midnight UTC.

Error Codes

All error responses use the same JSON shape. The code field is stable and machine-readable; error is human-readable.

json
{
  "error": "Field \"csv\" is required and must be a string",
  "code":  "INVALID_INPUT"
}
INVALID_INPUT 400 — A required field is missing, the template name is unrecognised, or the CSV/JSON is malformed.
PARSE_ERROR 400 — The request body could not be parsed as JSON.
INPUT_TOO_LARGE 413 — The request body exceeds the size limit for your tier.
RATE_LIMITED 429 — You have exceeded the daily report limit for your tier.
UNAUTHORIZED 401 — The API key is missing, invalid, or has been revoked.
INTERNAL_ERROR 500 — An unexpected server error occurred. Retry with exponential backoff.

POST /api/csv-to-report

Parse a CSV string and render it as a styled HTML report. The first row of your CSV must be a header row containing column names.

Request body fields
Field Type Description
csvrequired string Raw CSV text. First row is the header. Must have at least one data row.
templaterequired string One of: sales-summary, expense-report, inventory-status, invoice
titleoptional string Custom report title. Overrides the default template title.
delimiteroptional string Field delimiter character. Default: ,
Responses
200 Report generated. Returns { html, meta } — the html field is a complete, self-contained HTML document.
400 Invalid input — missing field, malformed CSV, or unknown template.
413 Input body exceeds the size limit for your tier.
429 Daily report limit exceeded.
curl
curl -X POST https://reportforge-api.vercel.app/api/csv-to-report \
  -H "Content-Type: application/json" \
  -d '{
    "csv": "item,amount,quantity,category\nWidget Pro,1250.00,50,Hardware\nGadget Plus,890.50,30,Electronics\nService Plan,2400.00,12,Services",
    "template": "sales-summary",
    "title": "Q1 2026 Sales Report"
  }'
Try It Out

POST /api/json-to-report

Render an array of JSON objects as a styled HTML report. Useful when your data is already structured in JavaScript or comes from a REST API.

Request body fields
Field Type Description
datarequired array Non-empty array of plain objects. All objects should share the same keys (column names).
templaterequired string One of: sales-summary, expense-report, inventory-status, invoice
titleoptional string Custom report title. Overrides the default template title.
Responses
200 Report generated. Returns { html, meta }.
400 Invalid input — missing field, non-array data, or unknown template.
413 Input body exceeds the size limit for your tier.
429 Daily report limit exceeded.
curl
curl -X POST https://reportforge-api.vercel.app/api/json-to-report \
  -H "Content-Type: application/json" \
  -d '{
    "data": [
      { "item": "Widget Pro", "amount": 1250.00, "quantity": 50, "category": "Hardware" },
      { "item": "Gadget Plus", "amount": 890.50, "quantity": 30, "category": "Electronics" }
    ],
    "template": "sales-summary",
    "title": "Q1 2026 Sales Report"
  }'
Try It Out

GET /api/templates

Returns the list of all available report templates, including required and optional column names. No authentication required. Useful for populating a template picker in your own UI.

Query parameters

None. This endpoint takes no parameters.

Response
200 Returns { templates: TemplateInfo[], usage: { csv, json } }.
curl
curl https://reportforge-api.vercel.app/api/templates
Try It Out