API Reference
The Kanalyze REST API lets you integrate financial data, variance reports, and AI narratives into your own systems. All endpoints are versioned at /api/v1.
Companies
List all companies in the authenticated organization.
Bearer token (session cookie or API key)Response
Array of company objects.{
"success": true,
"data": [
{
"id": "uuid",
"name": "Acme Corp",
"currency": "USD"
}
],
"error": null,
"meta": null
}Try it
curl -X GET "https://kanalyze.io/api/v1/companies" \ -H "Authorization: Bearer knz_YOUR_API_KEY"
Create a new company within the organization.
Bearer token (session cookie or API key)Request Body
Company name, optional industry and currency.{
"name": "Acme Corp",
"industry": "SaaS",
"currency": "USD"
}Response
The created company object.{
"success": true,
"data": {
"id": "uuid",
"name": "Acme Corp",
"currency": "USD",
"createdAt": "2025-01-01T00:00:00Z"
},
"error": null,
"meta": null
}Try it
curl -X POST "https://kanalyze.io/api/v1/companies" \
-H "Authorization: Bearer knz_YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"name":"Acme Corp","currency":"USD"}'Get a single company by ID.
Bearer token (session cookie or API key)Response
The company object.{
"success": true,
"data": {
"id": "uuid",
"name": "Acme Corp"
},
"error": null,
"meta": null
}Try it
curl -X GET "https://kanalyze.io/api/v1/companies/{companyId}" \
-H "Authorization: Bearer knz_YOUR_API_KEY"Update a company name, industry, or currency.
Bearer token (session cookie or API key)Request Body
Fields to update (all optional).{
"name": "Acme Corp Inc.",
"currency": "CAD"
}Response
The updated company object.{
"success": true,
"data": {
"id": "uuid",
"name": "Acme Corp Inc."
},
"error": null,
"meta": null
}Try it
curl -X PATCH "https://kanalyze.io/api/v1/companies/{companyId}" \
-H "Authorization: Bearer knz_YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"name":"Acme Corp Inc."}'Soft-delete a company (sets deleted_at, data is retained).
Bearer token (session cookie or API key)Response
204 No Content on success.{}Try it
curl -X DELETE "https://kanalyze.io/api/v1/companies/{companyId}" \
-H "Authorization: Bearer knz_YOUR_API_KEY"Uploads
Get a pre-signed S3 PUT URL to upload a financial file (CSV or XLSX). The client uploads directly to S3 using this URL, then calls /complete.
Bearer token (session cookie or API key)Request Body
Company ID, file name, period range, upload type.{
"companyId": "uuid",
"fileName": "jan-2025.csv",
"uploadType": "ACTUALS",
"periodStart": "2025-01-01",
"periodEnd": "2025-01-31"
}Response
Pre-signed URL and upload ID.{
"success": true,
"data": {
"uploadId": "uuid",
"presignedUrl": "https://s3.amazonaws.com/...",
"expiresAt": "2025-01-01T00:15:00Z"
},
"error": null,
"meta": null
}Try it
curl -X POST "https://kanalyze.io/api/v1/uploads/presign" \
-H "Authorization: Bearer knz_YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"companyId":"uuid","fileName":"jan-2025.csv","uploadType":"ACTUALS","periodStart":"2025-01-01","periodEnd":"2025-01-31"}'Signal that the S3 upload is complete. Triggers the PARSE_FINANCIAL_UPLOAD background job.
Bearer token (session cookie or API key)Request Body
Optional S3 ETag for deduplication.{
"s3ETag": "\"abc123\""
}Response
Background job ID to poll for status.{
"success": true,
"data": {
"jobId": "uuid",
"status": "PENDING"
},
"error": null,
"meta": null
}Try it
curl -X POST "https://kanalyze.io/api/v1/uploads/{uploadId}/complete" \
-H "Authorization: Bearer knz_YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"s3ETag":"\"abc123\""}'Variance (BvA)
Live Budget vs Actual variance for a company, period, and budget. Returns line-level variance without persisting a snapshot.
Bearer token (session cookie or API key)Response
Array of BvA lines with variance amounts and percentages. variancePercentage is a DECIMAL FRACTION of budget ("0.10" = 10%) — multiply by 100 for display.{
"success": true,
"data": [
{
"accountName": "Revenue",
"budgetAmount": "50000",
"actualAmount": "55000",
"varianceAmount": "5000",
"variancePercentage": "0.10",
"isFavorable": true
}
],
"error": null,
"meta": null
}Try it
curl -X GET "https://kanalyze.io/api/v1/companies/{companyId}/variance?budgetId=uuid&periodDate=2025-01-31" \
-H "Authorization: Bearer knz_YOUR_API_KEY"List persisted variance report snapshots for a company.
Bearer token (session cookie or API key)Response
Paginated list of variance reports.{
"success": true,
"data": [
{
"id": "uuid",
"status": "COMPLETE",
"periodDate": "2025-01-31",
"lineCount": 42
}
],
"error": null,
"meta": {
"returned": 1
}
}Try it
curl -X GET "https://kanalyze.io/api/v1/companies/{companyId}/variance-reports?limit=20&offset=0" \
-H "Authorization: Bearer knz_YOUR_API_KEY"Create a persisted variance report snapshot. Use async:true to run as a background job (recommended for large datasets).
Bearer token (session cookie or API key)Request Body
Budget ID, period date, variance thresholds, async flag.{
"budgetId": "uuid",
"periodDate": "2025-01-31",
"varianceThresholdAmount": "1000",
"varianceThresholdPercent": "5",
"async": true
}Response
201 sync with report data, or 202 async with jobId.{
"success": true,
"data": {
"jobId": "uuid"
},
"error": null,
"meta": null
}Try it
curl -X POST "https://kanalyze.io/api/v1/companies/{companyId}/variance-reports" \
-H "Authorization: Bearer knz_YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"budgetId":"uuid","periodDate":"2025-01-31","async":true}'Narratives
List AI-generated executive narratives for a company. The narrative EXPLAINS the deterministic health scorecard; it does not assign a grade. healthScore is historical only and is null on narratives generated from prompt narrative-executive-v2 onward — read the current grade from the health-trend endpoint.
Bearer token (session cookie or API key)Response
Array of narrative objects. healthScore is null except on pre-v2 historical rows.{
"success": true,
"data": [
{
"id": "uuid",
"periodDate": "2025-01-31",
"healthScore": null,
"status": "COMPLETE"
}
],
"error": null,
"meta": null
}Try it
curl -X GET "https://kanalyze.io/api/v1/companies/{companyId}/narratives?periodDate=2025-01-31" \
-H "Authorization: Bearer knz_YOUR_API_KEY"Generate a new AI executive narrative for a period. Optionally tie it to a variance report for richer analysis.
Bearer token (session cookie or API key)Request Body
Period date and optional variance report ID.{
"periodDate": "2025-01-31",
"varianceReportId": "uuid"
}Response
The generated narrative. healthScore is always null on new rows — the health grade comes from the deterministic scorecard, which the narrative explains.{
"success": true,
"data": {
"id": "uuid",
"healthScore": null,
"content": "Health score 68.4 (C). Revenue came in at $55K...",
"status": "COMPLETE"
},
"error": null,
"meta": null
}Try it
curl -X POST "https://kanalyze.io/api/v1/companies/{companyId}/narratives" \
-H "Authorization: Bearer knz_YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"periodDate":"2025-01-31"}'Budgets
List all budgets for a company.
Bearer token (session cookie or API key)Response
Array of budget objects.{
"success": true,
"data": [
{
"id": "uuid",
"name": "FY2025 Budget",
"fiscalYear": 2025,
"budgetType": "APPROVED"
}
],
"error": null,
"meta": null
}Try it
curl -X GET "https://kanalyze.io/api/v1/companies/{companyId}/budgets" \
-H "Authorization: Bearer knz_YOUR_API_KEY"Create a new budget for a company.
Bearer token (session cookie or API key)Request Body
Budget name, fiscal year, type.{
"name": "FY2025 Budget",
"fiscalYear": 2025,
"budgetType": "DRAFT"
}Response
The created budget object.{
"success": true,
"data": {
"id": "uuid",
"name": "FY2025 Budget"
},
"error": null,
"meta": null
}Try it
curl -X POST "https://kanalyze.io/api/v1/companies/{companyId}/budgets" \
-H "Authorization: Bearer knz_YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"name":"FY2025 Budget","fiscalYear":2025,"budgetType":"DRAFT"}'Integrations
List active accounting integrations (QuickBooks Online, Xero) for a company.
Bearer token (session cookie or API key)Response
Array of integration objects.{
"success": true,
"data": [
{
"id": "uuid",
"provider": "quickbooks",
"status": "CONNECTED",
"lastSyncedAt": "2025-01-31T08:00:00Z"
}
],
"error": null,
"meta": null
}Try it
curl -X GET "https://kanalyze.io/api/v1/companies/{companyId}/integrations" \
-H "Authorization: Bearer knz_YOUR_API_KEY"Initiate OAuth authorization for a new integration. Returns an authorization URL to redirect the user to.
Bearer token (session cookie or API key)Request Body
Provider name.{
"provider": "quickbooks"
}Response
OAuth authorization URL.{
"success": true,
"data": {
"authorizationUrl": "https://appcenter.intuit.com/connect/oauth2?..."
},
"error": null,
"meta": null
}Try it
curl -X POST "https://kanalyze.io/api/v1/companies/{companyId}/integrations" \
-H "Authorization: Bearer knz_YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"provider":"quickbooks"}'Company Metrics
Push monthly operational metric values (headcount, billable hours, units, …) keyed by the company’s stable metric_key. The programmatic third entry path beside manual grid entry and CSV/XLSX import — pushed values power the operational and industry KPI sections. Create an API key with scope "metrics:write" under Settings → Developer → API keys. The batch is atomic: any unknown metric_key or invalid entry rejects the whole request and nothing is written. Omit blank months (blank never becomes 0; a pushed 0 is a real zero); the API cannot delete values — clearing a cell is a dashboard action.
API key with scope metrics:writeRequest Body
Company id plus up to 5,000 entries. periodDate is the first of the month (YYYY-MM-01); value is a plain decimal string with up to 4 decimal places.{
"companyId": "uuid",
"entries": [
{
"metricKey": "headcount",
"periodDate": "2026-07-01",
"value": "13"
},
{
"metricKey": "billable_hours",
"periodDate": "2026-07-01",
"value": "1370.5"
}
]
}Response
Count of values written (created or updated).{
"success": true,
"data": {
"upserted": 2
},
"error": null,
"meta": null
}Try it
curl -X POST "https://kanalyze.io/api/v1/metrics/push" \
-H "Authorization: Bearer knz_YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"companyId":"uuid","entries":[{"metricKey":"headcount","periodDate":"2026-07-01","value":"13"}]}'Auth / Me
Export all personal data for the authenticated user as a ZIP archive (GDPR right of portability).
Bearer token (session cookie or API key)Response
ZIP file download containing JSON exports of all user data.Try it
curl -X GET "https://kanalyze.io/api/v1/me/data-export" \ -H "Authorization: Bearer knz_YOUR_API_KEY" \ --output data-export.zip
Request account deletion (GDPR right to erasure). Soft-deletes the user and schedules data purge.
Bearer token (session cookie or API key)Response
200 with confirmation message.{
"success": true,
"data": {
"message": "Account scheduled for deletion."
},
"error": null,
"meta": null
}Try it
curl -X DELETE "https://kanalyze.io/api/v1/me/account" \ -H "Authorization: Bearer knz_YOUR_API_KEY"
All responses follow the envelope format: {success, data, error, meta}. Errors include an HTTP status code (400–503) and a machine-readable code field.
Rate limits: 300 req/min standard, 30 req/min for AI endpoints (narratives, chat).