API Reference
REST API for automating your firm — TEAM and ENTERPRISE plans. Base URL: https://streamlinereports.com/api/v1
/api/v1/* endpoints require a TEAM or ENTERPRISE plan. Create API keys at Settings → Developer.Authentication
All requests must include an Authorization header with a Bearer token:
Authorization: Bearer sr_live_YOUR_KEY_HERECreating an API key
- Go to Settings → Developer (TEAM plan required; admin role required).
- Click Create API key.
- Give it a name and choose a scope: Read only or Read + Write.
- Copy the key — it's shown exactly once. Store it in your secret manager.
Scopes
| Scope | What it allows |
|---|---|
read | GET endpoints only — list and fetch clients, reports, templates, webhooks, firm info |
write | All GET endpoints plus POST, PATCH, DELETE — create reports, send, update clients, manage templates and webhook endpoints |
Key format
Keys start with sr_live_ followed by 32 random bytes in base64url encoding. The prefix enables automatic detection by GitHub secret scanning and Trufflehog — if you accidentally commit a key, it will be flagged.
First request
curl https://streamlinereports.com/api/v1/clients \
-H "Authorization: Bearer sr_live_YOUR_KEY"Rate limits
| Plan | Requests per hour | API keys | Webhook endpoints |
|---|---|---|---|
| TEAM | 1,000 | 3 | 5 |
| ENTERPRISE | 10,000 | Unlimited | 20 |
Rate limit state is tracked per API key. When you exceed the limit, the API returns 429 Too Many Requestswith a Retry-After: 3600 header plus these headers:
X-RateLimit-Limit: 1000
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 1715289600Response format
All responses use the same JSON envelope:
// Success
{ "data": { ... }, "error": null }
// List
{ "data": [...], "meta": { "total": 142, "page": 1, "perPage": 50, "hasMore": true }, "error": null }
// Error
{ "data": null, "error": { "code": "NOT_FOUND", "message": "Report not found" } }Errors
| Code | HTTP | Meaning |
|---|---|---|
UNAUTHORIZED | 401 | Missing or invalid API key |
PLAN_REQUIRED | 403 | Feature requires TEAM or ENTERPRISE plan |
INSUFFICIENT_SCOPE | 403 | Key lacks write scope for this endpoint |
NOT_FOUND | 404 | Resource not found or belongs to another firm |
CONFLICT | 409 | Duplicate — e.g. report already exists for this client + period |
VALIDATION_ERROR | 422 | Request body failed validation |
RATE_LIMITED | 429 | Too many requests — check Retry-After header |
PLAN_LIMIT | 402 | Plan limit reached (e.g. PDF generation quota) |
LIMIT_REACHED | 403 | Per-plan resource limit (e.g. max API keys or webhooks) |
INTERNAL_ERROR | 500 | Unexpected server error |
Clients
Returns a paginated list of your firm's clients.
| Param | Type | Description |
|---|---|---|
status | string | UP_TO_DATE, REPORT_DUE, or OVERDUE |
limit | integer | Results per page (max 100, default 50) |
page | integer | Page number (default 1) |
curl "https://streamlinereports.com/api/v1/clients?status=OVERDUE" \
-H "Authorization: Bearer sr_live_..."Updates a client. Only fields included in the body are changed.
| Field | Type | Description |
|---|---|---|
displayName | string | Client display name |
email | string | Contact email. Pass null to clear. |
notes | string | Internal notes. Pass null to clear. |
defaultTemplateId | string | Report template to auto-apply. Pass null to clear. |
reportDueDay | integer | Day of month report is due (1–31) |
curl -X PATCH "https://streamlinereports.com/api/v1/clients/clm_abc123" \
-H "Authorization: Bearer sr_live_..." \
-H "Content-Type: application/json" \
-d '{ "defaultTemplateId": "tpl_xyz", "reportDueDay": 10 }'Fires a client.updated webhook event on success.
Reports
Returns a paginated list of reports.
| Param | Type | Description |
|---|---|---|
clientId | string | Filter by client |
status | string | DRAFT, GENERATING, COMPLETE, ERROR, or SENT |
period | string | Filter by period in YYYY-MM format |
limit | integer | Max 100, default 50 |
page | integer | Default 1 |
curl "https://streamlinereports.com/api/v1/reports?clientId=clm_abc123&status=SENT" \
-H "Authorization: Bearer sr_live_..."Creates a new report. One report per client + period — returns 409 CONFLICT if a duplicate exists.
| Field | Required | Description |
|---|---|---|
clientId | ✓ | ID of the client this report is for |
period | ✓ | Reporting period in YYYY-MM format |
templateId | Clone blocks from this report template |
curl -X POST "https://streamlinereports.com/api/v1/reports" \
-H "Authorization: Bearer sr_live_..." \
-H "Content-Type: application/json" \
-d '{ "clientId": "clm_abc123", "period": "2026-03", "templateId": "tpl_xyz" }'Returns a single report including a summary of its blocks. Raw financial data is not exposed.
Deletes a report. Sent reports (status: SENT) cannot be deleted — returns 403 FORBIDDEN.
Triggers PDF generation. Uses a fast-path cache — if the report content is unchanged, returns COMPLETE immediately. Otherwise enqueues generation and returns 202 QUEUED.
// Immediate (cached)
{ "data": { "status": "COMPLETE", "downloadUrl": "https://..." } }
// Queued
{ "data": { "status": "QUEUED", "jobId": "job_..." } }Poll GET /reports/:id until status is COMPLETE, then fetch the PDF URL. A report.generated webhook fires when done.
Rate limited to 10 generation jobs per minute per firm (shared with dashboard usage).
Sends a report to an email address. Report must have a generated PDF (status: COMPLETE).
| Field | Required | Description |
|---|---|---|
to | ✓ | Recipient email address |
subject | Email subject (defaults to "[Client] — [Period] Financial Report") | |
body | Email body text |
Fires a report.sent webhook event on success.
Returns a signed download URL for the report PDF. URL is valid for 1 hour.
{ "data": { "url": "https://...", "filename": "Acme_2026-03.pdf", "expiresIn": 3600 } }Report templates
Report templates define a reusable block layout. System templates are read-only.
Lists all report templates — system templates and firm-created templates.
Creates a blank report template. Add blocks afterwards with POST /report-templates/:id/blocks.
| Field | Required | Description |
|---|---|---|
templateName | ✓ | Template name |
defaultPeriodType | none, monthly, quarterly, or annual |
curl -X POST "https://streamlinereports.com/api/v1/report-templates" \
-H "Authorization: Bearer sr_live_..." \
-H "Content-Type: application/json" \
-d '{ "templateName": "Monthly — Standard", "defaultPeriodType": "monthly" }'
# Then add blocks one at a time:
curl -X POST "https://streamlinereports.com/api/v1/report-templates/tpl_xyz/blocks" \
-H "Authorization: Bearer sr_live_..." \
-H "Content-Type: application/json" \
-d '{ "type": "PL" }'Valid block types include COVER_PAGE, PL, BALANCE_SHEET, CASH_FLOW, AR_AGING — the full list is in the ReportBlock schema of the OpenAPI spec.
Returns a single template with its full block list.
Adds a block to a template. System templates cannot be modified.
Deletes a firm-created template. System templates cannot be deleted.
Email templates
Email templates store reusable subject lines and body text with variables.{{client_name}}, {{firm_name}}, and {{period}} are substituted at send time.
Lists all email templates for the firm.
Creates a new email template.
curl -X POST "https://streamlinereports.com/api/v1/email-templates" \
-H "Authorization: Bearer sr_live_..." \
-H "Content-Type: application/json" \
-d '{
"name": "Monthly close",
"subject": "{{client_name}} — {{period}} Financial Report",
"body": "Hi {{client_name}},\n\nAttached is your {{period}} report.\n\n{{firm_name}}"
}'Returns a single email template.
Updates an email template. System templates cannot be modified.
Deletes a firm-created email template. System templates cannot be deleted.
Webhook endpoints
Manage webhook endpoints programmatically via the API, or use Settings → Developer in the dashboard. See the Webhooks guide for delivery, signatures, and retries.
Lists all registered webhook endpoints for the firm. Endpoints auto-paused after repeated delivery failures show pausedAt and disabledReason.
Registers a new endpoint. URL must be https:// and not resolve to a private IP address. Returns the signing secret — shown only once.
curl -X POST "https://streamlinereports.com/api/v1/webhooks" \
-H "Authorization: Bearer sr_live_..." \
-H "Content-Type: application/json" \
-d '{
"url": "https://your-server.com/webhooks/streamline",
"events": ["report.sent", "report.generated"],
"description": "n8n report pipeline"
}'Deactivates a webhook endpoint. Delivery history is retained and the endpoint still appears in the list with isActive: false.
Returns the last 100 delivery attempts for an endpoint.
Firm
Returns basic information about your firm. Does not include billing details or OAuth tokens.
{
"data": {
"id": "clm_...",
"name": "Your Firm",
"plan": "TEAM",
"seats": { "included": 3, "purchased": 1, "max": 10 }
}
}OpenAPI spec
A machine-readable OpenAPI 3.1 spec is available at:
GET https://streamlinereports.com/api/v1/openapi.jsonNo authentication required. Import it directly into:
- Claude Projects — Settings → Tools → Add custom tool → paste the URL
- GPT Actions — paste the URL in the action's schema field
- n8n — HTTP Request node → Import from OpenAPI
- Postman / Insomnia — Import → URL
Changelog
v1.3.0
Breaking: Subscribers endpoints and subscriber.* webhook events removed. Webhook delivery limits (1,000/day per firm) and auto-pause after 100 consecutive failures; endpoints expose pausedAt/disabledReason. Spec fixes: CUSTOM_CODE block type documented, phantom GET /clients/:id removed.
v1.2.0
Stricter request validation — out-of-contract bodies and query params now return 422 VALIDATION_ERRORinstead of being silently coerced.
v1.1.0
Report create/delete/generate endpoints. Client PATCH. Report template CRUD + block management. Email template CRUD. OpenAPI spec updated.
v1.0.0 — Initial release
Clients (read), Reports (read, send, pdf), Subscribers (read/write), Webhooks management, Firm (read), OpenAPI spec. API key management in dashboard.