Skip to content

Reports API

Build, execute, schedule, share, and export custom reports. All endpoints require JWT authentication and the analytics:read permission.

Note

For a user guide on creating and managing reports in the dashboard, see Reports.


Endpoints

CRUD

MethodPathDescription
GET/v1/reportsList reports
POST/v1/reportsCreate a report
GET/v1/reports/{id}Get a report
PUT/v1/reports/{id}Update a report
DELETE/v1/reports/{id}Delete a report
POST/v1/reports/{id}/duplicateDuplicate a report

Data Retrieval

MethodPathDescription
GET/v1/reports/{id}/dataExecute report and return data
GET/v1/reports/fieldsDiscover available metrics, dimensions, and filters
POST/v1/reports/queryAd-hoc query (live preview, no save)

Export

MethodPathDescription
GET/v1/reports/{id}/export/csvExport report as CSV
GET/v1/reports/{id}/export/pdfExport report as printable HTML/PDF

Sharing

MethodPathDescription
POST/v1/reports/{id}/shareCreate a shareable link
DELETE/v1/reports/{id}/shareRevoke a share link
GET/v1/reports/shared/{token}View shared report (public, no auth)

Scheduling

MethodPathDescription
POST/v1/reports/{id}/scheduleCreate a schedule
GET/v1/reports/{id}/scheduleGet schedule
PUT/v1/reports/{id}/scheduleUpdate schedule
DELETE/v1/reports/{id}/scheduleDelete schedule
POST/v1/reports/{id}/schedule/pausePause schedule
POST/v1/reports/{id}/schedule/resumeResume schedule

Pre-built Analysis

MethodPathDescription
POST/v1/reports/funnelEmail or flow funnel analysis
POST/v1/reports/cohortCohort retention analysis
POST/v1/reports/compare-flowsCompare 2--4 flows side by side
POST/v1/reports/flow-groupsFlow performance grouped by tags

Authentication

All endpoints (except /v1/reports/shared/{token}) require a JWT bearer token:

bash
curl "https://synapse-api.pyrx.tech/v1/reports" \
-H "Authorization: Bearer eyJhbGciOiJS..."

The authenticated user must have analytics:read permission. Missing permission returns:

json
{
"detail": "Missing permission: analytics:read"
}

List Reports

bash
curl "https://synapse-api.pyrx.tech/v1/reports?tab=all&sort_by=last_viewed_at&limit=20" \
-H "Authorization: Bearer eyJhbGciOiJS..."

Query Parameters

ParameterTypeDefaultDescription
tabstringallFilter: all, mine, shared, scheduled
report_typestringFilter by report type
visibilitystringFilter: private, workspace
created_bystringFilter by creator's member ID
searchstringSearch by name or description
sort_bystringlast_viewed_atSort: last_viewed_at, updated_at, name, created_at
sort_dirstringdescDirection: asc, desc
offsetinteger0Pagination offset
limitinteger50Items per page (1--100)

Response

json
{
"reports": [
{
"id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"tenant_id": "t1e2n3a4-n5t6-7890-abcd-ef1234567890",
"name": "Email Performance Overview",
"description": "Track email delivery, opens, clicks, and bounces over time.",
"report_type": "email_performance",
"config": {
"data_source": "email_logs",
"metrics": [
{ "field": "count", "label": "Sent" },
{ "field": "count", "label": "Delivered" },
{ "field": "rate", "label": "Open Rate", "numerator": "opened", "denominator": "delivered" }
],
"dimensions": [{ "field": "date", "granularity": "day" }],
"chart_type": "area",
"comparison_enabled": true,
"date_range_default": "30d"
},
"visibility": "workspace",
"is_template": true,
"created_by": null,
"last_viewed_at": "2026-04-18T10:30:00Z",
"share_token": null,
"share_expires_at": null,
"has_schedule": false,
"schedule_summary": null,
"created_at": "2026-04-01T00:00:00Z",
"updated_at": "2026-04-18T10:30:00Z"
}
],
"total": 12
}
Note

The first time you list reports, Synapse automatically creates pre-built report templates for your workspace. These have is_template: true and created_by: null.


Create a Report

bash
curl -X POST "https://synapse-api.pyrx.tech/v1/reports" \
-H "Authorization: Bearer eyJhbGciOiJS..." \
-H "Content-Type: application/json" \
-d '{
"name": "Weekly Click Analysis",
"description": "Click rates by flow, grouped weekly",
"report_type": "custom",
"config": {
"data_source": "email_logs",
"metrics": [
{ "field": "count", "label": "Sent" },
{ "field": "count", "label": "Clicked" },
{ "field": "rate", "label": "Click Rate", "numerator": "clicked", "denominator": "delivered" }
],
"dimensions": [
{ "field": "date", "granularity": "week" },
{ "field": "flow_name" }
],
"filters": [],
"chart_type": "bar",
"comparison_enabled": false,
"date_range_default": "30d"
},
"visibility": "workspace"
}'

Request Body

FieldTypeRequiredDescription
namestringYesReport name (1--255 characters)
descriptionstringNoDescription
report_typestringNoOne of: email_performance, flow_performance, contact_growth, deliverability, engagement, plan_usage, funnel_analysis, flow_comparison, flow_group_performance, custom (default)
configobjectNoReport configuration (see below)
visibilitystringNoprivate (default) or workspace

Config Object

FieldTypeDefaultDescription
data_sourcestringemail_logsData source: email_logs, flows, flow_trips, contacts, events
metricsarray[]Metrics to compute
dimensionsarray[]Dimensions to group by
filtersarray[]Filters to apply
chart_typestringlineChart type: line, bar, area, pie, table
comparison_enabledbooleanfalseEnable period-over-period comparison
date_range_defaultstring30dDefault date range

Response (201 Created)

Returns the full ReportResponse object (same shape as list items).


Get a Report

bash
curl "https://synapse-api.pyrx.tech/v1/reports/a1b2c3d4-e5f6-7890-abcd-ef1234567890" \
-H "Authorization: Bearer eyJhbGciOiJS..."

Returns the report metadata. Also updates last_viewed_at to the current time.


Execute Report (Get Data)

bash
curl "https://synapse-api.pyrx.tech/v1/reports/a1b2c3d4-e5f6-7890-abcd-ef1234567890/data?date_range=30d&compare=true" \
-H "Authorization: Bearer eyJhbGciOiJS..."

Query Parameters

ParameterTypeDefaultDescription
date_rangestringReport's defaultPreset: 1d, 7d, 30d, 90d, today, yesterday
from_datedatetimeExplicit start (overrides preset)
to_datedatetimeExplicit end (overrides preset)
comparebooleanfalseInclude comparison to previous period

Response

json
{
"report": { "...report metadata..." },
"kpis": [
{
"label": "Emails Sent",
"value": 12450,
"previous_value": 11200,
"trend": 11.2,
"subtitle": null
},
{
"label": "Open Rate",
"value": 39.77,
"previous_value": 37.5,
"trend": 6.1,
"subtitle": "4892 opened"
}
],
"chart_data": [
{
"dimensions": { "date": "2026-04-01" },
"metrics": { "sent": 1850, "delivered": 1820, "opened": 712, "clicked": 234, "bounced": 12 }
},
{
"dimensions": { "date": "2026-04-02" },
"metrics": { "sent": 1920, "delivered": 1900, "opened": 780, "clicked": 256, "bounced": 8 }
}
],
"table_data": [
{
"date": "2026-04-01",
"sent": 1850,
"delivered": 1820,
"opened": 712,
"clicked": 234,
"bounced": 12,
"open_rate": 39.12,
"click_rate": 12.86
}
],
"comparison_chart_data": [],
"date_range": {
"from": "2026-03-19T10:00:00+00:00",
"to": "2026-04-18T10:00:00+00:00",
"range": "30d"
}
}
Note

Results are cached for 5 minutes. The same report with the same date range returns cached data within that window.


Update a Report

bash
curl -X PUT "https://synapse-api.pyrx.tech/v1/reports/a1b2c3d4-e5f6-7890-abcd-ef1234567890" \
-H "Authorization: Bearer eyJhbGciOiJS..." \
-H "Content-Type: application/json" \
-d '{
"name": "Weekly Click Analysis (Updated)",
"visibility": "private"
}'

All fields are optional. Only the fields you include are updated.


Delete a Report

bash
curl -X DELETE "https://synapse-api.pyrx.tech/v1/reports/a1b2c3d4-e5f6-7890-abcd-ef1234567890" \
-H "Authorization: Bearer eyJhbGciOiJS..."

Returns 204 No Content on success. Also deletes any associated schedule and share link.


Duplicate a Report

bash
curl -X POST "https://synapse-api.pyrx.tech/v1/reports/a1b2c3d4-e5f6-7890-abcd-ef1234567890/duplicate" \
-H "Authorization: Bearer eyJhbGciOiJS..."

Creates a copy with " (Copy)" appended to the name. The duplicate is always private visibility with no schedule or share link.

Returns 201 Created with the new report.


Field Discovery

bash
curl "https://synapse-api.pyrx.tech/v1/reports/fields" \
-H "Authorization: Bearer eyJhbGciOiJS..."

Response

json
{
"categories": [
{
"id": "email",
"label": "Email",
"icon": "mail",
"fields": [
{
"id": "email_sent",
"label": "Emails Sent",
"category": "email",
"field_type": "metric",
"data_type": "number",
"description": "Total emails sent (queued + delivered)",
"operators": []
},
{
"id": "email_open_rate",
"label": "Open Rate",
"category": "email",
"field_type": "metric",
"data_type": "rate",
"description": "Percentage of delivered emails opened",
"operators": []
},
{
"id": "email_status",
"label": "Email Status",
"category": "email",
"field_type": "dimension",
"data_type": "string",
"description": "Delivery status (sent, delivered, opened, etc.)",
"operators": [
{ "value": "eq", "label": "is" },
{ "value": "neq", "label": "is not" },
{ "value": "contains", "label": "contains" },
{ "value": "in", "label": "in" },
{ "value": "is_empty", "label": "is empty" }
]
}
]
},
{
"id": "flow",
"label": "Flow",
"icon": "git-branch",
"fields": ["..."]
},
{
"id": "contact",
"label": "Contact",
"icon": "users",
"fields": ["..."]
},
{
"id": "event",
"label": "Event",
"icon": "zap",
"fields": ["..."]
}
]
}

Ad-hoc Query

Execute a report configuration without saving it. Used for the report builder's live preview.

bash
curl -X POST "https://synapse-api.pyrx.tech/v1/reports/query" \
-H "Authorization: Bearer eyJhbGciOiJS..." \
-H "Content-Type: application/json" \
-d '{
"config": {
"data_source": "email_logs",
"metrics": [
{ "field": "count", "label": "Sent" },
{ "field": "rate", "label": "Open Rate", "numerator": "opened", "denominator": "delivered" }
],
"dimensions": [{ "field": "date", "granularity": "day" }],
"chart_type": "line"
},
"date_range": "7d",
"compare": false
}'

Request Body

FieldTypeDefaultDescription
configobjectRequiredSame config object as POST /v1/reports
date_rangestring30dPreset date range
from_datestringISO 8601 start date
to_datestringISO 8601 end date
comparebooleanfalseInclude comparison period

Returns the same ReportDataResponse as GET /v1/reports/{id}/data.


CSV Export

bash
curl "https://synapse-api.pyrx.tech/v1/reports/a1b2c3d4-e5f6-7890-abcd-ef1234567890/export/csv?date_range=30d" \
-H "Authorization: Bearer eyJhbGciOiJS..." \
-o report.csv

Query Parameters

ParameterTypeDefaultDescription
date_rangestringReport's defaultPreset date range
from_datedatetimeExplicit start date
to_datedatetimeExplicit end date

Returns a text/csv streaming response with Content-Disposition: attachment header.


PDF Export

bash
curl "https://synapse-api.pyrx.tech/v1/reports/a1b2c3d4-e5f6-7890-abcd-ef1234567890/export/pdf?date_range=30d" \
-H "Authorization: Bearer eyJhbGciOiJS..."

Returns an HTML page styled for printing. The page automatically triggers the browser's print dialog via JavaScript. Table data is limited to 100 rows.


Share a Report

bash
curl -X POST "https://synapse-api.pyrx.tech/v1/reports/a1b2c3d4-e5f6-7890-abcd-ef1234567890/share" \
-H "Authorization: Bearer eyJhbGciOiJS..." \
-H "Content-Type: application/json" \
-d '{ "expires_in_days": 14 }'
FieldTypeDefaultDescription
expires_in_daysinteger7Link validity: 1--90 days

Response

json
{
"share_token": "dGhpcyBpcyBhIHRlc3QgdG9rZW4...",
"share_url": "https://synapse-api.pyrx.tech/v1/reports/shared/dGhpcyBpcyBhIHRlc3QgdG9rZW4...",
"expires_at": "2026-05-02T10:00:00Z"
}

View Shared Report (Public)

bash
curl "https://synapse-api.pyrx.tech/v1/reports/shared/dGhpcyBpcyBhIHRlc3QgdG9rZW4...?date_range=7d"

No authentication required. Returns the same ReportDataResponse as the authenticated data endpoint.

bash
curl -X DELETE "https://synapse-api.pyrx.tech/v1/reports/a1b2c3d4-e5f6-7890-abcd-ef1234567890/share" \
-H "Authorization: Bearer eyJhbGciOiJS..."

Returns 204 No Content.


Schedule a Report

Create Schedule

bash
curl -X POST "https://synapse-api.pyrx.tech/v1/reports/a1b2c3d4-e5f6-7890-abcd-ef1234567890/schedule" \
-H "Authorization: Bearer eyJhbGciOiJS..." \
-H "Content-Type: application/json" \
-d '{
"frequency": "weekly",
"day_of_week": 0,
"hour": 9,
"timezone": "Asia/Singapore",
"date_range_type": "previous_7d",
"recipients": [
{ "email": "[email protected]", "name": "Marketing Team" },
{ "email": "[email protected]", "name": "Manager" }
],
"format_options": {
"chart_image": false,
"csv_attachment": true,
"kpi_only": false
}
}'

Request Body

FieldTypeRequiredDescription
frequencystringYesdaily, weekly, or monthly
day_of_weekintegerWeekly only0 (Mon) -- 6 (Sun)
day_of_monthintegerMonthly only1--28
hourintegerNoHour of day, 0--23 (default: 9)
timezonestringNoIANA timezone (default: UTC)
date_range_typestringNoprevious_day, previous_7d (default), previous_30d, previous_month, mtd
recipientsarrayYes1--10 recipients, each with email (required) and name (optional)
format_optionsobjectNochart_image, csv_attachment, kpi_only (all boolean, default false)

Response (201 Created)

json
{
"id": "s1c2h3e4-d5u6-7890-abcd-ef1234567890",
"report_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"frequency": "weekly",
"day_of_week": 0,
"day_of_month": null,
"hour": 9,
"timezone": "Asia/Singapore",
"date_range_type": "previous_7d",
"recipients": [
{ "email": "[email protected]", "name": "Marketing Team" },
{ "email": "[email protected]", "name": "Manager" }
],
"format_options": {
"chart_image": false,
"csv_attachment": true,
"kpi_only": false
},
"is_active": true,
"last_sent_at": null,
"next_send_at": "2026-04-21T01:00:00Z",
"created_at": "2026-04-18T10:00:00Z",
"updated_at": "2026-04-18T10:00:00Z"
}
Warning

Each report can have only one schedule. Attempting to create a second schedule returns 409 Conflict. Use PUT to update the existing schedule instead.

Get Schedule

bash
curl "https://synapse-api.pyrx.tech/v1/reports/a1b2c3d4-e5f6-7890-abcd-ef1234567890/schedule" \
-H "Authorization: Bearer eyJhbGciOiJS..."

Update Schedule

bash
curl -X PUT "https://synapse-api.pyrx.tech/v1/reports/a1b2c3d4-e5f6-7890-abcd-ef1234567890/schedule" \
-H "Authorization: Bearer eyJhbGciOiJS..." \
-H "Content-Type: application/json" \
-d '{ "hour": 14, "timezone": "UTC" }'

All fields are optional. Only provided fields are updated. The next_send_at is recalculated automatically.

Delete Schedule

bash
curl -X DELETE "https://synapse-api.pyrx.tech/v1/reports/a1b2c3d4-e5f6-7890-abcd-ef1234567890/schedule" \
-H "Authorization: Bearer eyJhbGciOiJS..."

Returns 204 No Content.

Pause / Resume

bash
# Pause
curl -X POST "https://synapse-api.pyrx.tech/v1/reports/a1b2c3d4-e5f6-7890-abcd-ef1234567890/schedule/pause" \
-H "Authorization: Bearer eyJhbGciOiJS..."
 
# Resume
curl -X POST "https://synapse-api.pyrx.tech/v1/reports/a1b2c3d4-e5f6-7890-abcd-ef1234567890/schedule/resume" \
-H "Authorization: Bearer eyJhbGciOiJS..."

Both return the updated ScheduleResponse. Pausing sets is_active: false. Resuming sets is_active: true and recalculates next_send_at.


Error Codes

StatusCodeDescription
403Missing analytics:read permission
404Report or schedule not found
409Schedule already exists (use PUT to update)
410Shared link has expired
422Validation error (e.g., missing flow_id for flow funnel, missing day_of_week for weekly schedule)