Export Report Data via Maxio API
Applies to: Maxio Core
Last updated on Oct 16, 2026
Maxio provides a comprehensive API for running reports and exporting their data programmatically. Use it to automate recurring report pulls, sync report data into your own systems, or build custom integrations, instead of relying on the Maxio user interface to run and download reports manually.
The Reports API allows you to:
- Execute predefined reports or one-click reports.
- Monitor report execution status.
- Export report results in multiple formats.
- Retrieve exported files for download.
API endpoints overview
The Reports API uses the following base endpoints:
- Report Definitions:
/{your-instance}/api/v1.0/reports/definitions/ - Report Runs:
/{your-instance}/api/v1.0/reports/runs/ - Report Exports:
/{your-instance}/api/v1.0/reports/exports/
Replace
{your-instance}with your specific Maxio instance identifier. You can find this in your account settings or by checking the URL when logged into your Maxio dashboard.
Authentication
All API requests require proper authentication. Refer to the main API documentation for details on authentication methods and required headers. For complete API reference documentation, including all available parameters and response schemas, consult the OpenAPI documentation available in your Maxio instance.
Working with report definitions
Before running reports, you may want to explore what reports are available in your account. Report Definitions are read-only through this API. You can list and retrieve them, but creating, editing, or deleting a report definition requires the Maxio user interface.
Listing available reports
GET /{your-instance}/api/v1.0/reports/definitions/Available Filters:
name=Revenue- Filter by report name (partial match).description=monthly- Filter by description (partial match).type=financial- Filter by report type.tag=important- Filter by applied tags.one_click_report_group=uuid- Filter by one-click report group.created_by=123- Filter by user who created the report.modified__gte=2025-01-01T00:00:00.000000- Filter by modification date.
Sorting Options:
id,name,description,type,created_by,one_click_report_group,modified
Getting report details
GET /{your-instance}/api/v1.0/reports/definitions/123/This returns the complete structure of a specific report definition, including its configuration and parameters.
Basic workflow
Step 1: Run a report
To execute a report, make a POST request to /{your-instance}/api/v1.0/reports/runs/ with one of the following approaches:
Option A: Using a Report Definition ID
POST /{your-instance}/api/v1.0/reports/runs/
{
"report_definition": 123,
"export_format_name": "csv"
}Option B: Using a One-Click Report UUID
POST /{your-instance}/api/v1.0/reports/runs/
{
"one_click_report": "uuid-string-here",
"export_format_name": "csv"
}Available Export Formats:
"csv"- Legacy CSV format"gsheets"- Legacy Google Sheets format"ucsv"- Unified CSV format"tgsheets"- Tabbed Google Sheets format"xlsx"- Excel format"xlsx1d"- OneDrive format
"ucsv"only works for reports built on the Generic Report Builder, such as Advanced Subscription Momentum, Finance Details by Transaction, and Days Sales Outstanding. Requesting it for any other report type fails.
Optional: Run as of a different date
To run a report as of a specific date without editing its saved definition, add as_of_date (YYYY-MM-DD) to the request:
POST /{your-instance}/api/v1.0/reports/runs/
{
"report_definition": 123,
"as_of_date": "2026-06-30",
"export_format_name": "csv"
}The run uses that date in place of the definition's own as-of setting, including a relative setting such as :months=0. The saved report definition stays as it is, so later runs without as_of_date keep using its normal setting. You can use as_of_date with either report_definition or one_click_report.
These report types accept as_of_date:
- Deferred Revenue by Transaction (report type
Finance Details by Transaction): the date must be the last day of a month. - A/R Aging: any date. If the definition's Aging Method is Current, this run ages as of the date you send, the same as the As of Date method, and the definition stays on Current.
Maxio Core rejects the request with a 400 error, and doesn't create a run, in these cases:
- The report is any other type, such as Top Customers.
- The report definition has Multi-Site turned on.
- The date for a Deferred Revenue by Transaction report isn't a month end.
The error is returned under the as_of_date key. Leaving as_of_date out, or sending null, runs the report on its saved setting.
The API response includes the run ID and URL for tracking progress:
{
"id": "456",
"url": "/api_path/reports/runs/456/"
}Step 2: Monitor run status
Check the execution status by making a GET request to the run URL:
GET /{your-instance}/api/v1.0/reports/runs/456/The response includes detailed status information:
{
"id": 456,
"status": "Completed",
"duration_secs": "12.5",
"timestamp": "2025-01-15T10:30:00Z",
"user_full_name": "John Doe",
"report_name": "Top Customers by Revenue",
"report_type": "Top Customers",
"as_of_date": "2025-01-31",
"failure_message": null
}Possible Status Values:
"Running"- Report is currently executing."Completed"- Report finished successfully."Failed"- Report execution failed.
Wait until the
statusbecomes"Completed"before proceeding to retrieve results.
as_of_date is the single date this run's figures are as of, resolved when generation started. Deferred Revenue by Transaction, A/R Aging, and Top Customers runs populate it, including resolving a relative or fiscal-period setting such as a report definition's :quarters=-1 into the actual calendar date it meant on the day the run executed. For a run created with an as_of_date override, it returns the date you requested. Other report types, and any run from before this field existed, return null because they have no single as-of date to report.
Step 3: Retrieve report data
You have two options for accessing the report results:
Option A: Direct CSV Download (for smaller reports)
GET /{your-instance}/api/v1.0/reports/runs/456/?mode=csvThis streams the CSV data directly in the response. This method is ideal for smaller reports that can be processed immediately.
Option B: Create a Persistent Export (recommended for larger reports)
- Create an export:
POST /{your-instance}/api/v1.0/reports/exports/
{
"report_run": 456,
"format_name": "csv"
}- Monitor the export status:
GET /{your-instance}/api/v1.0/reports/exports/789/The response includes export details:
{
"id": 789,
"status": "Completed",
"report_run": 456,
"format_name": "csv",
"timestamp": "2025-01-15T10:35:00Z",
"url": "https://storage.example.com/exports/report_789.csv",
"failure_message": null
}Export Status Values:
"Scheduled"- Export is queued for processing."Running"- Export is being generated."Completed"- Export is ready for download."Failed"- Export generation failed."Viewed"- Export has been accessed.
- Once the export status is
"Completed", retrieve the file:
GET /{your-instance}/api/v1.0/reports/exports/789/?redirect=1The redirect=1 parameter redirects you directly to the downloadable file.
Option C: Row-Level JSON Results
Instead of a CSV or spreadsheet export, you can pull a run's results directly as structured JSON:
GET /{your-instance}/api/v1.0/reports/runs/456/results/Without a section parameter, this returns the run's metadata plus the list of its sections (each section's name, label, and how deep its rows expand). Add ?section=<name> to also get that section's columns and one page of rows:
GET /{your-instance}/api/v1.0/reports/runs/456/results/?section=momentum&page=1&page_size=100Available query parameters:
section- A section'snamefrom the sections list; omit it to see only that list.page- Page of rows to return (default 1).page_size- Rows per page (default 100, maximum 1000).expansion_level- Deepest row expansion level to include; omit for all levels.
Each row carries a row_key (either a stable database ID or a positional index — the run's store_in_db field tells you which), its key_values and result_values. The section's total_count is counted before paging, so you can tell when a page has cut off more rows. The response also carries definitional_basis: settings, such as Momentum Calculation Basis on the Advanced Subscription Momentum Report, that change what the figures themselves mean rather than just how they're grouped.
Each column in that list carries a column_index (cite cells by it), key, label, column_type (key or result), expansion_level, and linkable. The linkable flag tells you whether cells in that column can resolve to a record: when it's true, open a cell at /{your-instance}/so/reports/log/{id}/link/g/{section}/r{row_key}c{column_index}/ and you're redirected to the record, or for some report types a drilldown report, behind the figure. A cell in a column flagged false answers 404 at that route instead, and so does an empty cell in any column. A few cells in a true column also answer 404, such as a summary row on Finance Details by Transaction or a percent or ratio row in some drilldown sections. Which columns a report type flags linkable varies by report: Advanced Subscription Momentum flags its record key columns (customer, contract, subscription and similar) and the period columns of its drilldown sections, such as MRR Momentum, while excluding its Full Range column and drilldown reports themselves; Top Customers flags its customer name and number columns; and Finance Details by Transaction flags its transaction number column and any group-by column with a known record page. A report type that hasn't implemented links flags no column linkable.
Like
ucsv, this endpoint only works for reports built on the Generic Report Builder, such as Advanced Subscription Momentum, Finance Details by Transaction, and Days Sales Outstanding. Requesting it for another report type returns an error. If the run's stored results have already been purged, the endpoint returns a 410 response — run the report again to regenerate them.
Retaining a run's results via the API
By default, a report run's stored results are purged 5 days after it completes — the same window the Report History page's Retain option controls. To keep a specific run's results past that window from the API:
POST /{your-instance}/api/v1.0/reports/runs/456/retain/
{
"keep": true
}Set "keep": false to release a previously retained run back to the normal purge schedule. The response echoes the run's id, its keep_serialized_data flag, and its expires datetime (null while retained).
You can also turn on retention when you create the run, by adding "keep_serialized_data": true alongside report_definition or one_click_report in the initial POST /reports/runs/ request.
Managing reports and exports
Listing report runs
View all your report runs with optional filtering and sorting:
GET /{your-instance}/api/v1.0/reports/runs/Available Filters:
report_definition=123- Filter by specific report definition ID.one_click_report=uuid- Filter by one-click report UUID.status=Completed- Filter by status (Running, Completed, Failed).user=456- Filter by user ID who ran the report.report_name=Sales- Filter by report name (partial match).report_type=summary- Filter by report type.timestamp__gte=2025-01-01T00:00:00.000000- Filter by date range (after).timestamp__lt=2025-02-01T00:00:00.000000- Filter by date range (before).
Sorting Options:
Use the sort parameter with any of these fields:
timestamp- Sort by execution time.duration_secs- Sort by execution duration.user- Sort by the ID of the user who ran the report.user_full_name- Sort by user name.report_name- Sort by report name.report_type- Sort by report type.data_format- Sort by data format.report_definition- Sort by report definition ID.status- Sort by status.
Example with filters:
GET /{your-instance}/api/v1.0/reports/runs/?status=Completed&report_type=sales&sort=timestampListing exports
Similarly, you can list and filter exports:
GET /{your-instance}/api/v1.0/reports/exports/Available Filters:
report_run=456- Filter by specific report run ID.report_definition=123- Filter by report definition ID.status=Completed- Filter by export status.format_name=csv- Filter by export format.report_name=Monthly- Filter by report name (partial match).report_type=summary- Filter by report type.timestamp__gte=2025-01-01T00:00:00.000000- Filter by date range.
Sorting Options:
report_run,report_definition,timestamp,format_name,report_name,report_type,status
Example:
GET /{your-instance}/api/v1.0/reports/exports/?status=Completed&format_name=csv&sort=timestampBest practices
- Choose the Right Approach: Use
export_format_namewhen creating a report run to automatically trigger export creation, especially for larger datasets. - Don't Mix Report Types: Specify either
report_definitionorone_click_reportwhen creating a run, but never both. - Poll Responsibly: When monitoring status, implement reasonable polling intervals (e.g., every 5-10 seconds) to avoid overwhelming the API.
- Handle Large Reports: For reports that may generate large datasets, always use the persistent export approach rather than direct CSV streaming.
- Use Filtering: Take advantage of the filtering parameters when listing runs and exports to find specific results quickly.
- Date Format Consistency: When using datetime filters, always use the format
YYYY-MM-DDTHH:MM:SS.000000(e.g.,2025-01-15T14:30:00.000000). - Pagination: Use the
pageparameter for large result sets and check thenextandpreviousURLs in responses for navigation.
Error handling
Common scenarios to handle in your implementation:
- Invalid Report IDs: Ensure your report definition IDs are valid and accessible.
- Long-Running Reports: Some reports may take several minutes to complete - implement appropriate timeout handling.
- Export Failures: Check export status and handle failed exports appropriately by examining the
failure_messagefield. - Rate Limiting: Implement proper retry logic with exponential backoff for API requests.
- Empty Results: Handle cases where reports complete successfully but contain no data.
Troubleshooting
Report run fails
- Check that the report definition ID exists and is accessible to your user.
- Verify that editable report definitions are being used (some reports may be read-only).
- Review the
failure_messagefield in the response for specific error details.
Export never completes
- Monitor the export status regularly.
- Check system status if exports remain in "Running" state for extended periods.
- Contact support if exports consistently fail with specific report types.
Direct CSV download issues
- Use the
mode=csvparameter only for smaller reports. - Switch to persistent exports for large datasets.
- Ensure the report run status is "Completed" before attempting CSV download.
Related information
For an overview of exporting data from Maxio, including how to initiate an export from the user interface, see Understand Data Export.
Still need help?
Reach out and our support team will take it from here.
