Report Export API
Exporting vendor reports via the PartnerStack API
This guide covers how to programmatically trigger report exports and receive the resulting files through either a webhook callback or polling.
Overview
There are two API endpoints involved:
| Endpoint | Method | Purpose | Docs link |
|---|---|---|---|
/api/v2/vendor_report_export/{vendor_report_configuration_key} | POST | Trigger a new export for a saved report | https://docs.partnerstack.com/reference/post_v2-vendor-report-export-vendor-report-configuration-key |
/api/v2/vendor_report_export/export/{vendor_report_export_key} | GET | Check the status of an export and retrieve download URLs | https://docs.partnerstack.com/reference/get_v2-vendor-report-export-export-vendor-report-export-key |
Both endpoints require Basic Auth using your API key and secret.
Step 1: Trigger an Export
Request
POST https://api.partnerstack.com/api/v2/vendor_report_export/{vendor_report_configuration_key}
Path parameters:
| Parameter | Description |
|---|---|
vendor_report_configuration_key | The key of the saved report configuration to export (e.g. vrc_123456). You can find this by calling the List Report Configurations endpoint — each configuration in the response includes its key. It is also visible in the URL when viewing the report in the PartnerStack dashboard. |
Request body:
| Field | Type | Required | Description |
|---|---|---|---|
member_email | string | Yes | The email of a team member on your PartnerStack account. This user must have access to your PartnerStack instance. They will receive an email notification when the export completes. |
webhook_target_url | string | No | A URL where PartnerStack will POST the export results (including download links) once the export completes successfully. |
show_unexpanded | boolean | No | When true, includes unexpanded/raw data in the export. Defaults to false. |
Example request:
{
"member_email": "[email protected]",
"webhook_target_url": "https://your-server.com/webhooks/partnerstack-export"
}Response
The response includes a data.key field (e.g. vrex_abc123) which you can use to poll for results. At this stage the export is queued — files will be empty and zip_file will be null.
{
"data": {
"key": "vrex_abc123",
"status": "queued",
"report_type": "partner_team_member_report",
"vendor_report_configuration_key": "vrc_123456",
"source": "api",
"created_at": 1710734400000,
"updated_at": 1710734400000,
"files": [],
"zip_file": null,
"webhook_target_url": "https://your-server.com/webhooks/partnerstack-export",
},
"message": "Vendor report export queued and can take up to 30 minutes",
"status": 200
}Rate limits
- Per report: Only one export per report configuration + member email combination every 2 hours. If an export for that combination already exists, a
429response is returned. - Per member: A maximum of 20 active exports per member email every 2 hours. A
429response is returned if this limit is exceeded.
Step 2: Receive the Export Results
You have three options for receiving export results. Use whichever best fits your integration.
Option A: Direct Webhook via webhook_target_url (Recommended)
webhook_target_url (Recommended)If you provide a webhook_target_url in the POST request, PartnerStack will send a POST request directly to that URL once the export completes successfully.
Webhook behavior:
- Fires only on successful exports (status =
success). - Retries up to 3 times if your endpoint returns a non-2xx response, with progressive backoff (10 seconds, 20 seconds, 30 seconds between retries).
- Each request has a 10-second timeout — your endpoint must respond within that window.
- The payload is sent as
Content-Type: application/json.
Webhook payload:
The export entity is sent directly as the root JSON object:
{
"key": "vrex_abc123",
"status": "success",
"report_type": "partner_team_member_report",
"vendor_report_configuration_key": "vrc_123456",
"source": "api",
"created_at": 1710734400000,
"updated_at": 1710738000000,
"expires_at": 1710907200000,
"files": [
{
"key": "file_abc1",
"name": "partner_team_member_report-abc123.csv",
"url": "https://storage.googleapis.com/...?signature=..."
}
],
"zip_file": null,
"file_key": "file_abc1",
"zip_file_key": null,
"target_key": "comp_123456",
"exporter_key": "mem_123456",
"webhook_target_url": "https://your-server.com/webhooks/partnerstack-export",
"report_config": { "...": "..." },
"recipients": { "membership_keys": ["mem_123456"] },
"configuration": {},
"retry_count": 0,
"error": null,
"admin_user_key": null,
"scheduler_key": null
}Option B: Webhook Events API (vendor_report_export.completed)
vendor_report_export.completed)Alternatively, you can register a webhook subscription through the Webhooks API for the vendor_report_export.completed event. This webhook fires for all completed exports on your account — including in-app exports, scheduled exports, and API-triggered exports — regardless of whether a webhook_target_url was set.
- Create a webhook subscription:
POST https://api.partnerstack.com/api/v2/webhooks
{
"target_url": "https://your-server.com/webhooks/partnerstack",
"event": "vendor_report_export.completed"
}- The payload is wrapped in an event envelope:
{
"event": "vendor_report_export.completed",
"data": {
"key": "vrex_abc123",
"status": "success",
"report_type": "partner_team_member_report",
"vendor_report_configuration_key": "vrc_123456",
"files": [
{
"key": "file_abc1",
"name": "partner_team_member_report-abc123.csv",
"url": "https://storage.googleapis.com/...?signature=..."
}
],
"zip_file": null,
}
}This webhook fires for ALL completed exports on your account, not just API-triggered ones. Use the
sourcefield ("api","in_app", or"scheduled") to filter if needed.
Option C: Poll the Export Status Endpoint
Use the key returned from the initial POST request to check the export status:
GET https://api.partnerstack.com/api/v2/vendor_report_export/export/{vendor_report_export_key}
Example:
GET https://api.partnerstack.com/api/v2/vendor_report_export/export/vrex_abc123
Response when still processing:
{
"data": {
"key": "vrex_abc123",
"status": "queued",
"files": [],
"zip_file": null,
"...": "..."
},
"message": "Vendor report export retrieved",
"status": 200
}Response when complete:
{
"data": {
"key": "vrex_abc123",
"status": "success",
"report_type": "partner_team_member_report",
"files": [
{
"key": "file_abc1",
"name": "partner_team_member_report-abc123.csv",
"url": "https://storage.googleapis.com/...?signature=..."
}
],
"zip_file": null,
"expires_at": 1710907200000,
"...": "..."
},
"message": "Vendor report export retrieved",
"status": 200
}Export statuses:
| Status | Meaning |
|---|---|
queued | The export is being generated. Exports can take up to 30 minutes. |
success | The export completed successfully. Download URLs are available in files and/or zip_file. |
failure | The export failed. Check the error field for details. |
expired | The export’s download links have expired (~2 days after generation). File URLs will no longer be accessible. |
Step 3: Download the Report Files
Once the export status is success, download the files from the signed URLs provided in the response.
Single file export
Most exports produce a single CSV file in the files array:
"files": [
{
"key": "file_abc1",
"name": "partner_team_member_report-abc123.csv",
"url": "https://storage.googleapis.com/...?signature=..."
}
]Download the file from the url.
Multi-file exports
Large exports may be automatically split into multiple CSV files. When this happens:
- The
filesarray will contain multiple entries, one per file. - A
zip_fileobject will also be populated, containing a single zip archive of all the files.
"files": [
{
"key": "file_part1",
"name": "partner_team_member_report-abc123-000000000000.csv",
"url": "https://storage.googleapis.com/...part1?signature=..."
},
{
"key": "file_part2",
"name": "partner_team_member_report-abc123-000000000001.csv",
"url": "https://storage.googleapis.com/...part2?signature=..."
}
],
"zip_file": {
"key": "file_zip1",
"name": "partner_team_member_report-abc123.zip",
"url": "https://storage.googleapis.com/...zip?signature=..."
}You can either:
- Download each file individually from the
filesarray, or - Download the single
zip_filewhich contains all parts
Important notes about download URLs
- Download URLs are signed and time-limited. They expire approximately 2 days after the export is generated.
- If you need to re-download after expiry, you must trigger a new export.
- Individual CSV files can be up to approximately 1 GB in size. If the total export data exceeds this, the export is split into multiple files.
Report Types
The report_type field identifies which type of report was exported. Use this to determine how to process the downloaded CSV data.
| Report Type | Description |
|---|---|
click_report | Link performance data |
customer_report | Customer performance data |
partner_team_member_report | Partner performance data |
product_performance_report | Product performance metrics |
lead_report | Lead performance data |
deal_report | Deal performance data |
partner_activation_report | Partner activity data |
The report_config Object
report_config ObjectThe report_config object is included in the export response and webhook payloads. It contains the saved report’s filters, groupings, and sorting that were applied when generating the export. This is useful for understanding what data the export contains without opening the CSV.
Top-level fields:
| Field | Type | Description |
|---|---|---|
filters | object | Filter criteria applied to the report. See filter fields below. |
groupings | object | How the report data is grouped. Contains primary_grouping and secondary_grouping (both strings, may be empty ""). |
order_by | string or array | Column(s) used to sort results. Prefix with - for descending (e.g. "-revenue_amount_usd"). |
hidden_fields | array of strings | Columns excluded from the export output. |
action_options | array of strings | Action types included in the export (applies to partner_team_member_report when actions are visible). |
Common filter fields (present across all report types):
| Filter Field | Type | Description |
|---|---|---|
start_date | integer | Start of the date range (epoch milliseconds). |
end_date | integer | End of the date range (epoch milliseconds). |
date_range_key | string | Named date range preset (e.g. "last_7_days", "last_30_days", "last_90_days", "last_12_months", "this_month", "this_year", etc.). |
group_keys | array of strings | Filter by partner group keys (e.g. ["grup_123456"]). |
partnership_keys | array of strings | Filter by partnership keys. |
product_keys | array of strings | Filter by product keys. |
team_stack_keys | array of strings | Filter by program/team stack keys. |
locations | array of strings | Filter by location short codes (e.g. ["US", "CA"]). |
Example report_config:
{
"filters": {
"start_date": 1690070400000,
"end_date": 1721779199000,
"date_range_key": "last_12_months",
"group_keys": [],
"partnership_keys": [],
"product_keys": [],
"team_stack_keys": [],
"locations": []
},
"groupings": {
"primary_grouping": "partner_team_name",
"secondary_grouping": ""
},
"order_by": ["-revenue_amount_usd"],
"hidden_fields": [],
"action_options": []
}The
report_configreflects the saved report configuration at the time of export. Not all filter fields are present on every report type — only the fields relevant to that report type will appear. Empty arrays and empty strings indicate no filter was applied for that field.
Setting Up Scheduled Exports (In-App)
You can configure exports to run automatically on a schedule from the PartnerStack dashboard:
- Navigate to the Performance section in the PartnerStack dashboard.
- Create and save the report you want to export (or select an existing saved report).
- Click Export to open the export drawer, then select the Scheduled occurrence option.
- Configure the schedule frequency (weekly, monthly, etc.), recipients, and other options.
- (Optional) Set a Webhook URL: When “Scheduled” is selected, a Webhook URL section appears in the export drawer. Enter the URL where you’d like PartnerStack to send the download link when each scheduled export completes. This is the same
webhook_target_urlbehavior described in Option A — PartnerStack will POST the export payload directly to that URL each time the scheduled export finishes. - Save the scheduled export.
Once configured:
- Every time the scheduled export runs, it will generate a new export and send the webhook payload to the configured webhook URL (if one was provided).
- Note: If you have a
vendor_report_export.completedwebhook subscription (via the Webhooks API), you will receive a webhook payload for all completed exports — including scheduled exports, one-off in-app exports, and API-triggered exports. - The webhook URL configured on a scheduled export applies only to exports generated by that schedule. One-off manual exports will not use it unless a
webhook_target_urlis also provided via the API.
Full Integration Example
Here is a typical integration flow using the webhook_target_url approach:
1. POST /api/v2/vendor_report_export/vrc_123456
Body: {
"member_email": "[email protected]",
"webhook_target_url": "https://app.example.com/webhooks/partnerstack/report-export"
}
2. PartnerStack queues the export (can take up to 30 minutes)
3. PartnerStack POSTs the completed export to your webhook_target_url
Payload includes: files[].url, zip_file.url, report_type, status
4. Your server downloads the CSV file(s) from the signed URL(s)
5. Your server processes/stores the report data as needed
And here is the same flow using polling:
1. POST /api/v2/vendor_report_export/vrc_123456
Body: { "member_email": "..." }
→ Save the returned "key" (e.g. "vrex_abc123")
2. Poll: GET /api/v2/vendor_report_export/export/vrex_abc123
→ Repeat until status is "success" or "failure"
→ Recommended polling interval: every 30-60 seconds
3. When status = "success", download files from files[].url
4. Process/store the report data as needed
Error Handling
| HTTP Status | Meaning |
|---|---|
400 | Missing required fields (member_email) or company context not found. |
401 | Invalid or missing Basic Auth credentials. |
403 | The member email does not have access to the company, or the report configuration does not belong to your company. |
404 | The export key was not found (GET endpoint). |
429 | Rate limit exceeded — either an export for this report+member already exists within the past 2 hours, or the member has reached the maximum of 20 active exports. |

