HeldSway

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.

Authorization: Bearer <access_token>

Endpoints

Method Path Scope Throttle Description
GET /v1/reports/stats reports:read 120/min Aggregate statistics and trends
GET /v1/reports/commission-chart reports:read 120/min Time-series data for charting
GET /v1/reports/top-affiliates reports:read 120/min Top affiliates by earnings
GET /v1/reports/clicks-by-campaign reports:read 120/min Clicks grouped by campaign
GET /v1/reports/payouts reports:read 120/min Payout history (paginated)
GET /v1/reports/export reports:read 30/min CSV export of report data

Common Query Parameters

Most report endpoints share these optional date range filters:

Parameter Type Default Constraints Description
from date 30 days ago YYYY-MM-DD Start of date range
to date today YYYY-MM-DD, must be >= from End of date range

Report Stats — GET /v1/reports/stats

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

Example

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

Success Response — HTTP 200

{
  "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

Field Type Description
total_commission_paid number Sum of commission_amount from approved conversions in the date range
pending_payouts number Approved commission minus completed payouts (owed but not yet paid)
conversion_rate number Percentage of referral clicks that resulted in a conversion
total_referral_clicks integer Total distinct referral click sessions in the date range
trends.commission_paid number % change vs previous period (positive = increase)
trends.pending_payouts number Reserved — always 0.0 (trend requires payout history)
trends.conversion_rate number Absolute percentage-point change vs previous period
trends.referral_clicks number % change vs previous period
filters.from string Applied start date (YYYY-MM-DD)
filters.to string Applied 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

Parameter Type Required Default Constraints Description
from date No 30 days ago YYYY-MM-DD Start of date range
to date No today YYYY-MM-DD End of date range
granularity string No daily daily, weekly, monthly Time bucket size

Example

curl "api.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

{
  "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

Field Type Description
granularity string Applied granularity (daily, weekly, or monthly)
labels string[] Human-readable time bucket labels
data number[] Sum of commission_amount for each time bucket (2 decimal places)
filters.from string Applied start date
filters.to string Applied end date

Label Format by Granularity

Granularity Format Example
daily MMM DD Apr 01
weekly MMM DD – MMM DD Apr 01 – Apr 07
monthly MMM YYYY Apr 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

Parameter Type Required Default Constraints Description
from date No 30 days ago YYYY-MM-DD Start of date range
to date No today YYYY-MM-DD End of date range
limit integer No 10 1–50 Maximum number of affiliates to return

Example

curl "api.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

{
  "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

Field Type Description
items[].affiliate_id integer Affiliate record ID
items[].name string Affiliate user’s display name
items[].referral_code string Affiliate’s referral code
items[].earned number Total commission earned in the date range (2 decimal places)
items[].clicks integer Total referral clicks attributed to this affiliate
items[].conversions integer Total conversions attributed to this affiliate
filters.from string Applied start date
filters.to string Applied 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

Parameter Type Required Default Constraints Description
from date No 30 days ago YYYY-MM-DD Start of date range
to date No today YYYY-MM-DD End of date range
limit integer No 10 1–50 Maximum number of campaigns to return

Example

curl "api.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

{
  "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

Field Type Description
items[].campaign string|null Campaign tag from the referral link (null = links with no campaign assigned)
items[].clicks integer Total referral clicks for links with this campaign tag
filters.from string Applied start date
filters.to string Applied 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

Parameter Type Required Default Constraints Description
from date No 30 days ago YYYY-MM-DD Start of date range
to date No today YYYY-MM-DD End of date range
status string No all pending, completed, failed Filter by payout status
affiliate_id integer No all Affiliate ID Filter by affiliate
per_page integer No 15 1–100 Items per page
page integer No 1 min:1 Page number

Example

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

Success Response — HTTP 200

{
  "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

Field Type Description
items[].id integer Payout record ID
items[].affiliate_id integer Affiliate record ID
items[].affiliate_name string Affiliate user’s display name
items[].amount number Payout amount (2 decimal places)
items[].currency string 3-letter currency code (default USD)
items[].method string|null Payment method (bank_transfer, paypal, check, other)
items[].status string pending, completed, or failed
items[].reference string|null External transaction reference/ID
items[].paid_at string|null ISO 8601 timestamp when payment was completed (null if pending/failed)
items[].created_at string ISO 8601 timestamp of payout record creation
meta.current_page integer Current page number
meta.per_page integer Items per page
meta.total integer Total matching records
meta.last_page integer Last 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

Parameter Type Required Default Constraints Description
from date No 30 days ago YYYY-MM-DD Start of date range
to date No today YYYY-MM-DD End of date range
sections string No all Comma-separated list Sections to include in the export

Available Sections

Section Key Description
stats Headline metrics with trend percentages
commission_chart Commission over time (daily granularity)
top_affiliates Top affiliates ranked by earnings
clicks_by_campaign Click counts grouped by campaign
payouts Payout history

Example

curl "api.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/csv Content-Disposition: attachment; filename="affiliate-reports-2026-04-16.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

  ┌─────────┐
  │ 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 Status Error Code Cause
401 UNAUTHORIZED Missing or invalid Bearer token
403 FORBIDDEN Token does not have reports:read scope
422 VALIDATION_ERROR Invalid query parameters (bad date format, invalid granularity, etc.)
429 Rate limit exceeded
500 REPORT_ERROR Internal error during report generation

Error Response Format

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

Rate Limiting

Endpoint Group Limit
Read endpoints (stats, chart, tables, payouts) 120 requests/min
Export 30 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

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

Success Response — 200 OK

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

Response Fields

Field Type Description
total integer Total number of referral links (active + inactive)
active integer Links with is_active = true
inactive integer Links with is_active = false
total_clicks integer Sum 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.