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:

EndpointMethodPurposeDocs link
/api/v2/vendor_report_export/{vendor_report_configuration_key}POSTTrigger a new export for a saved reporthttps://docs.partnerstack.com/reference/post_v2-vendor-report-export-vendor-report-configuration-key
/api/v2/vendor_report_export/export/{vendor_report_export_key}GETCheck the status of an export and retrieve download URLshttps://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:

ParameterDescription
vendor_report_configuration_keyThe 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:

FieldTypeRequiredDescription
member_emailstringYesThe 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_urlstringNoA URL where PartnerStack will POST the export results (including download links) once the export completes successfully.
show_unexpandedbooleanNoWhen 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 429 response is returned.
  • Per member: A maximum of 20 active exports per member email every 2 hours. A 429 response 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)

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)

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.

  1. 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"
}
  1. 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 source field ("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:

StatusMeaning
queuedThe export is being generated. Exports can take up to 30 minutes.
successThe export completed successfully. Download URLs are available in files and/or zip_file.
failureThe export failed. Check the error field for details.
expiredThe 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 files array will contain multiple entries, one per file.
  • A zip_file object 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 files array, or
  • Download the single zip_file which 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 TypeDescription
click_reportLink performance data
customer_reportCustomer performance data
partner_team_member_reportPartner performance data
product_performance_reportProduct performance metrics
lead_reportLead performance data
deal_reportDeal performance data
partner_activation_reportPartner activity data

The report_config Object

The 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:

FieldTypeDescription
filtersobjectFilter criteria applied to the report. See filter fields below.
groupingsobjectHow the report data is grouped. Contains primary_grouping and secondary_grouping (both strings, may be empty "").
order_bystring or arrayColumn(s) used to sort results. Prefix with - for descending (e.g. "-revenue_amount_usd").
hidden_fieldsarray of stringsColumns excluded from the export output.
action_optionsarray of stringsAction types included in the export (applies to partner_team_member_report when actions are visible).

Common filter fields (present across all report types):

Filter FieldTypeDescription
start_dateintegerStart of the date range (epoch milliseconds).
end_dateintegerEnd of the date range (epoch milliseconds).
date_range_keystringNamed date range preset (e.g. "last_7_days", "last_30_days", "last_90_days", "last_12_months", "this_month", "this_year", etc.).
group_keysarray of stringsFilter by partner group keys (e.g. ["grup_123456"]).
partnership_keysarray of stringsFilter by partnership keys.
product_keysarray of stringsFilter by product keys.
team_stack_keysarray of stringsFilter by program/team stack keys.
locationsarray of stringsFilter 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_config reflects 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:

  1. Navigate to the Performance section in the PartnerStack dashboard.
  2. Create and save the report you want to export (or select an existing saved report).
  3. Click Export to open the export drawer, then select the Scheduled occurrence option.
  4. Configure the schedule frequency (weekly, monthly, etc.), recipients, and other options.
  5. (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_url behavior described in Option A — PartnerStack will POST the export payload directly to that URL each time the scheduled export finishes.
  6. 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.completed webhook 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_url is 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 StatusMeaning
400Missing required fields (member_email) or company context not found.
401Invalid or missing Basic Auth credentials.
403The member email does not have access to the company, or the report configuration does not belong to your company.
404The export key was not found (GET endpoint).
429Rate 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.