Skip to content

Affiliate Reports API ​

GET /v1/reports/*

Fetch affiliate analytics data for a business. Supports multiple data sections (stats, trends, charts, tables, and paginated activity feeds), each with optional metric filtering and date range scoping.

Authentication ​

All endpoints require a Bearer access token with the reports:read scope.

text
Authorization: Bearer <access_token>

Endpoints ​

MethodPathScopeThrottleDescription
GET/v1/reports/statsreports:read120/minAggregate statistics and trends
GET/v1/reports/commission-chartreports:read120/minTime-series data for charting
GET/v1/reports/top-affiliatesreports:read120/minTop affiliates by earnings
GET/v1/reports/clicks-by-campaignreports:read120/minClicks grouped by campaign
GET/v1/reports/payoutsreports:read120/minPayout history (paginated)
GET/v1/reports/exportreports:read30/minCSV export of report data

Common Query Parameters ​

Most report endpoints share these optional date range filters:

ParameterTypeDefaultConstraintsDescription
fromdate30 days agoYYYY-MM-DDStart of date range
todatetodayYYYY-MM-DD, must be >= fromEnd of date range

Report Stats — GET /v1/reports/stats ​

Returns aggregated summary statistics and period-over-period trend data.

Example ​

bash
curl "https://heldsway.com/api/v1/reports/stats?from=2026-03-17&to=2026-04-16" \
  -H "Authorization: Bearer <access_token>"

Success Response — HTTP 200 ​

json
{
  "success": true,
  "message": "Report statistics retrieved.",
  "data": {
    "total_commission_paid": 28.00,
    "pending_payouts": 14.00,
    "conversion_rate": 3.2,
    "total_referral_clicks": 2,
    "trends": {
      "commission_paid": 14.0,
      "pending_payouts": 0.0,
      "conversion_rate": 1.1,
      "referral_clicks": -8.3
    },
    "filters": {
      "from": "2026-03-17",
      "to": "2026-04-16"
    }
  }
}

Response Fields ​

FieldTypeDescription
total_commission_paidnumberSum of commission_amount from approved conversions in the date range
pending_payoutsnumberApproved commission minus completed payouts (owed but not yet paid)
conversion_ratenumberPercentage of referral clicks that resulted in a conversion
total_referral_clicksintegerTotal distinct referral click sessions in the date range
trends.commission_paidnumber% change vs previous period (positive = increase)
trends.pending_payoutsnumberReserved — always 0.0 (trend requires payout history)
trends.conversion_ratenumberAbsolute percentage-point change vs previous period
trends.referral_clicksnumber% change vs previous period
filters.fromstringApplied start date (YYYY-MM-DD)
filters.tostringApplied end date (YYYY-MM-DD)

Trend Calculation ​

Trends compare the requested date range against the immediately preceding period of equal length. For example, if from=2026-03-17 and to=2026-04-16 (31 days), the previous period is 2026-02-14 to 2026-03-16.

  • Commission and clicks: ((current - previous) / previous) * 100, rounded to 1 decimal place. Returns 0.0 when the previous period value is zero.
  • Conversion rate: Absolute difference in percentage points (current_rate - previous_rate), rounded to 1 decimal place.

Commission Chart — GET /v1/reports/commission-chart ​

Returns time-series data for rendering a commission-over-time bar chart. Supports daily, weekly, or monthly granularity.

Query Parameters ​

ParameterTypeRequiredDefaultConstraintsDescription
fromdateNo30 days agoYYYY-MM-DDStart of date range
todateNotodayYYYY-MM-DDEnd of date range
granularitystringNodailydaily, weekly, monthlyTime bucket size

Example ​

bash
curl "https://heldsway.com/api/v1/reports/commission-chart?from=2026-04-01&to=2026-04-16&granularity=daily" \
  -H "Authorization: Bearer <access_token>"

Success Response — HTTP 200 ​

json
{
  "success": true,
  "message": "Commission chart data retrieved.",
  "data": {
    "granularity": "daily",
    "labels": ["Apr 01", "Apr 02", "Apr 03", "Apr 04", "Apr 05"],
    "data": [4.50, 0.00, 12.00, 0.00, 7.00],
    "filters": {
      "from": "2026-04-01",
      "to": "2026-04-16"
    }
  }
}

Response Fields ​

FieldTypeDescription
granularitystringApplied granularity (daily, weekly, or monthly)
labelsstring[]Human-readable time bucket labels
datanumber[]Sum of commission_amount for each time bucket (2 decimal places)
filters.fromstringApplied start date
filters.tostringApplied end date

Label Format by Granularity ​

GranularityFormatExample
dailyMMM DDApr 01
weeklyMMM DD – MMM DDApr 01 – Apr 07
monthlyMMM YYYYApr 2026

Empty time buckets are filled with 0.00 to ensure the chart has no gaps.


Top Affiliates — GET /v1/reports/top-affiliates ​

Returns the top-performing affiliates ranked by commission earned within the date range. Only affiliates with at least one conversion or click in the period are included.

Query Parameters ​

ParameterTypeRequiredDefaultConstraintsDescription
fromdateNo30 days agoYYYY-MM-DDStart of date range
todateNotodayYYYY-MM-DDEnd of date range
limitintegerNo101–50Maximum number of affiliates to return

Example ​

bash
curl "https://heldsway.com/api/v1/reports/top-affiliates?from=2026-03-17&to=2026-04-16&limit=5" \
  -H "Authorization: Bearer <access_token>"

Success Response — HTTP 200 ​

json
{
  "success": true,
  "message": "Top affiliates retrieved.",
  "data": {
    "items": [
      {
        "affiliate_id": 1,
        "name": "Salman",
        "referral_code": "SALMAN2026",
        "earned": 140.00,
        "clicks": 2,
        "conversions": 5
      }
    ],
    "filters": {
      "from": "2026-03-17",
      "to": "2026-04-16"
    }
  }
}

Response Fields ​

FieldTypeDescription
items[].affiliate_idintegerAffiliate record ID
items[].namestringAffiliate user's display name
items[].referral_codestringAffiliate's referral code
items[].earnednumberTotal commission earned in the date range (2 decimal places)
items[].clicksintegerTotal referral clicks attributed to this affiliate
items[].conversionsintegerTotal conversions attributed to this affiliate
filters.fromstringApplied start date
filters.tostringApplied end date

Clicks by Campaign — GET /v1/reports/clicks-by-campaign ​

Returns referral click counts grouped by the campaign tag on referral links. All active campaigns for the business are included, even those with zero clicks in the date range.

Query Parameters ​

ParameterTypeRequiredDefaultConstraintsDescription
fromdateNo30 days agoYYYY-MM-DDStart of date range
todateNotodayYYYY-MM-DDEnd of date range
limitintegerNo101–50Maximum number of campaigns to return

Example ​

bash
curl "https://heldsway.com/api/v1/reports/clicks-by-campaign?from=2026-03-17&to=2026-04-16" \
  -H "Authorization: Bearer <access_token>"

Success Response — HTTP 200 ​

json
{
  "success": true,
  "message": "Clicks by campaign retrieved.",
  "data": {
    "items": [
      {
        "campaign": "mountain_rentals_brand",
        "clicks": 0
      },
      {
        "campaign": "women_skier_interest",
        "clicks": 0
      },
      {
        "campaign": "winter_sale",
        "clicks": 0
      },
      {
        "campaign": null,
        "clicks": 2
      }
    ],
    "filters": {
      "from": "2026-03-17",
      "to": "2026-04-16"
    }
  }
}

Response Fields ​

FieldTypeDescription
items[].campaignstring|nullCampaign tag from the referral link (null = links with no campaign assigned)
items[].clicksintegerTotal referral clicks for links with this campaign tag
filters.fromstringApplied start date
filters.tostringApplied end date

Results are ordered by clicks descending. The null campaign entry (representing links without a campaign tag) is always listed last.


Payouts — GET /v1/reports/payouts ​

Returns a paginated list of payout records with optional filtering by status and affiliate.

Query Parameters ​

ParameterTypeRequiredDefaultConstraintsDescription
fromdateNo30 days agoYYYY-MM-DDStart of date range
todateNotodayYYYY-MM-DDEnd of date range
statusstringNoallpending, completed, failedFilter by payout status
affiliate_idintegerNoallAffiliate IDFilter by affiliate
per_pageintegerNo151–100Items per page
pageintegerNo1min:1Page number

Example ​

bash
curl "https://heldsway.com/api/v1/reports/payouts?status=completed&per_page=10" \
  -H "Authorization: Bearer <access_token>"

Success Response — HTTP 200 ​

json
{
  "success": true,
  "message": "Payouts retrieved.",
  "data": {
    "items": [
      {
        "id": 1,
        "affiliate_id": 1,
        "affiliate_name": "Salman",
        "amount": 28.00,
        "currency": "USD",
        "method": "bank_transfer",
        "status": "completed",
        "reference": "TXN-20260410-001",
        "paid_at": "2026-04-10T14:30:00.000000Z",
        "created_at": "2026-04-10T14:00:00.000000Z"
      }
    ],
    "meta": {
      "current_page": 1,
      "per_page": 15,
      "total": 1,
      "last_page": 1
    },
    "filters": {
      "from": "2026-03-17",
      "to": "2026-04-16"
    }
  }
}

Response Fields ​

FieldTypeDescription
items[].idintegerPayout record ID
items[].affiliate_idintegerAffiliate record ID
items[].affiliate_namestringAffiliate user's display name
items[].amountnumberPayout amount (2 decimal places)
items[].currencystring3-letter currency code (default USD)
items[].methodstring|nullPayment method (bank_transfer, paypal, check, other)
items[].statusstringpending, completed, or failed
items[].referencestring|nullExternal transaction reference/ID
items[].paid_atstring|nullISO 8601 timestamp when payment was completed (null if pending/failed)
items[].created_atstringISO 8601 timestamp of payout record creation
meta.current_pageintegerCurrent page number
meta.per_pageintegerItems per page
meta.totalintegerTotal matching records
meta.last_pageintegerLast available page

Date Range Behavior ​

Date range filters are applied differently based on payout status:

  • Completed payouts: filtered by paid_at (when the payment was made)
  • Pending/failed payouts: filtered by created_at (when the payout was recorded)

This ensures completed payouts appear in the period they were paid, not when they were initially created.


Export Report — GET /v1/reports/export ​

Downloads a CSV file containing report data. By default exports all sections; use the sections parameter to select specific sections.

Query Parameters ​

ParameterTypeRequiredDefaultConstraintsDescription
fromdateNo30 days agoYYYY-MM-DDStart of date range
todateNotodayYYYY-MM-DDEnd of date range
sectionsstringNoallComma-separated listSections to include in the export

Available Sections ​

Section KeyDescription
statsHeadline metrics with trend percentages
commission_chartCommission over time (daily granularity)
top_affiliatesTop affiliates ranked by earnings
clicks_by_campaignClick counts grouped by campaign
payoutsPayout history

Example ​

bash
curl "https://heldsway.com/api/v1/reports/export?from=2026-04-01&to=2026-04-16&sections=stats,top_affiliates" \
  -H "Authorization: Bearer <access_token>" \
  -o affiliate-reports.csv

Success Response — HTTP 200 ​

Content-Type: text/csvContent-Disposition: attachment; filename="affiliate-reports-2026-04-16.csv"

csv
"--- Report Stats ---"
Metric,Value,Trend (%)
Total Commission Paid,28.00,14.0
Pending Payouts,14.00,0.0
Conversion Rate (%),3.2,1.1
Total Referral Clicks,2,-8.3

"--- Top Affiliates ---"
Name,Referral Code,Earned,Clicks,Conversions
Salman,SALMAN2026,140.00,2,5

"--- Clicks by Campaign ---"
Campaign,Clicks
mountain_rentals_brand,0
women_skier_interest,0
winter_sale,0
(no campaign),2

"--- Commission Over Time (daily) ---"
Date,Commission
Apr 01,4.50
Apr 02,0.00
Apr 03,12.00

"--- Payouts ---"
Affiliate,Amount,Currency,Method,Status,Reference,Paid At,Created At
Salman,28.00,USD,bank_transfer,completed,TXN-20260410-001,2026-04-10 14:30:00,2026-04-10 14:00:00

CSV Structure ​

  • Each section is separated by a header row in the format --- Section Name ---
  • Sections appear in the order: stats, top affiliates, clicks by campaign, commission chart, payouts
  • When sections is specified, only the requested sections appear
  • Unknown section keys in the sections parameter are silently ignored
  • Payout timestamps use YYYY-MM-DD HH:MM:SS format (not ISO 8601)

Payout Status Workflow ​

text
  ┌─────────┐
  │ pending │ ← initial state (payout recorded)
  └────┬────┘
       │
  ┌────┴────┐
  ▼         ▼
┌─────────┐ ┌────────┐
│completed│ │ failed │
└─────────┘ └────────┘
  • pending: Payout has been recorded but not yet processed
  • completed: Payment was successfully processed (paid_at is set)
  • failed: Payment processing failed

Error Reference ​

HTTP StatusError CodeCause
401UNAUTHORIZEDMissing or invalid Bearer token
403FORBIDDENToken does not have reports:read scope
422VALIDATION_ERRORInvalid query parameters (bad date format, invalid granularity, etc.)
429—Rate limit exceeded
500REPORT_ERRORInternal error during report generation

Error Response Format ​

json
{
  "success": false,
  "error": {
    "code": "VALIDATION_ERROR",
    "message": "Validation failed",
    "details": {
      "granularity": ["The selected granularity is invalid."]
    }
  }
}

Rate Limiting ​

Endpoint GroupLimit
Read endpoints (stats, chart, tables, payouts)120 requests/min
Export30 requests/min

Exceeding the limit returns HTTP 429 Too Many Requests.


Returns aggregate statistics for all referral links in your business.

GET /v1/links/stats

  • Required scope: affiliates:read
  • Rate limit: 120 requests/minute

Example Request ​

bash
curl "https://heldsway.com/api/v1/links/stats" \
  -H "Authorization: Bearer <access_token>"

Success Response — 200 OK ​

json
{
  "success": true,
  "message": "OK",
  "data": {
    "total": 42,
    "active": 38,
    "inactive": 4,
    "total_clicks": 1523
  }
}

Response Fields ​

FieldTypeDescription
totalintegerTotal number of referral links (active + inactive)
activeintegerLinks with is_active = true
inactiveintegerLinks with is_active = false
total_clicksintegerSum of click_count across all links

Note: Soft-deleted links are excluded from all counts. total_clicks is derived from the denormalized click_count field on each link, which is incremented in real time by the click tracking system.

Released under the MIT License.