Reports API
Report Assembly
List reports
http
GET /orgs/:orgId/reportsOptional query params:
?projectId=uuid— filter by project?status=published— filter by status (draft,published)
Response
json
[
{
"id": "uuid",
"title": "Q1 2026 Donor Report — WASH Program",
"projectId": "uuid",
"projectName": "Rwanda WASH Phase 1",
"reportType": "quarterly",
"startDate": "2026-01-01",
"endDate": "2026-03-31",
"status": "published",
"shareToken": "uuid",
"shareUrl": "https://app.impactmel.com/r/uuid",
"createdAt": "2026-04-02T08:00:00Z"
}
]Create and assemble report
http
POST /orgs/:orgId/reportsUsing reporting periods:
json
{
"title": "Q1 2026 Donor Report",
"projectId": "uuid",
"reportType": "quarterly",
"periodIds": ["uuid-q1-2026"]
}Using custom date range:
json
{
"title": "FY2025-26 Annual Review",
"projectId": "uuid",
"reportType": "annual",
"startDate": "2025-07-01",
"endDate": "2026-06-30"
}Response: 201 Created with assembled report including all sections.
The assembly engine:
- Resolves which
ReportingPeriodrows overlap the date range - Loads
approved+submittedindicator reports in those periods - Aggregates values by each indicator's
aggregationMethod - Falls back to date-overlap filter if no period rows found
- Attaches activities, budget summary, and attachments
Get report
http
GET /orgs/:orgId/reports/:idResponse (assembled report with sections)
json
{
"id": "uuid",
"title": "Q1 2026 Donor Report",
"project": { "id": "uuid", "name": "Rwanda WASH Phase 1", ... },
"startDate": "2026-01-01",
"endDate": "2026-03-31",
"status": "published",
"sections": {
"executiveSummary": "...",
"challengesLessons": "...",
"indicators": [
{
"indicatorName": "# of people with access to clean water",
"code": "WASH-01",
"unit": "people",
"value": 4250,
"target": 5000,
"progressPct": 85,
"status": "at_risk",
"narrative": "...",
"resultNode": { "level": "output", "title": "500 water points installed" }
}
],
"activities": [...],
"budget": {
"totalPlanned": 125000,
"totalActual": 98500,
"burnRate": 78.8,
"lines": [...]
}
}
}Update report narrative
http
PATCH /orgs/:orgId/reports/:idjson
{
"sections": {
"executiveSummary": "Updated summary text...",
"challengesLessons": "Key challenge: delayed procurement due to...",
"recommendations": "Going forward, we recommend..."
}
}Publish report
http
PATCH /orgs/:orgId/reports/:id
{ "status": "published" }Delete report
http
DELETE /orgs/:orgId/reports/:idReturns 204 No Content. Revoking an active share link also happens automatically.
Share Links
Generate share link
http
PATCH /orgs/:orgId/reports/:id/shareResponse
json
{
"shareToken": "550e8400-e29b-41d4-a716-446655440000",
"shareUrl": "https://app.impactmel.com/r/550e8400-e29b-41d4-a716-446655440000"
}Regenerate share link
http
PATCH /orgs/:orgId/reports/:id/share/regenerateThe old token is immediately invalidated.
Revoke share link
http
DELETE /orgs/:orgId/reports/:id/shareSets shareToken = null. All existing public links return 404.
Public Report (No Auth)
Get public report
http
GET /reports/share/:tokenNo authentication required. Returns the same full report object as the authenticated endpoint.
Returns 404 if:
- Token doesn't exist
- Token has been revoked
- Token has expired (if
shareExpiresAtis set)