HeldSway

Orders & Commissions API

Manage tracked conversions, line-item order details, commission review, approvals, bulk moderation, and CSV exports across all store locations.


Manage tracked conversions (orders), view commission statistics, approve or reject pending commissions, and export data.


Authentication

All endpoints require a Bearer access token with the appropriate scope. See Authentication.

Scope Access
orders:read List, show, stats, export
orders:write Approve, reject, bulk approve, bulk reject

Endpoints

Method Path Scope Throttle Description
GET /v1/orders orders:read 120/min List orders (paginated)
GET /v1/orders/stats orders:read 120/min Aggregated statistics
GET /v1/orders/export orders:read 30/min CSV export
GET /v1/orders/{id} orders:read 120/min Single order detail
POST /v1/orders/{id}/approve orders:write 60/min Approve pending order
POST /v1/orders/{id}/reject orders:write 60/min Reject pending order
POST /v1/orders/bulk-approve orders:write 60/min Bulk approve
POST /v1/orders/bulk-reject orders:write 60/min Bulk reject

List Orders — GET /v1/orders

Returns a paginated list of conversions with filtering, sorting, and search.

Query Parameters

Parameter Type Required Default Constraints Description
search string No — max:255 Search by order ID or affiliate name
status string No — pending, approved, rejected, cancelled Filter by conversion status
affiliate_id integer No — Valid affiliate ID for this business Filter by affiliate
from date No — YYYY-MM-DD or ISO 8601 date-time Start of date range (inclusive). A bare date starts at 00:00:00 UTC; a date-time is used as an exact instant
to date No — YYYY-MM-DD or ISO 8601 date-time, must be >= from End of date range (inclusive). A bare date ends at 23:59:59 UTC; a date-time is used as an exact instant
attribution string No all all, attributed, unattributed Filter by attribution state
location_id string No — max:64 Filter by store location ID
source_domain string No — max:255 Filter by origin storefront domain
sort string No converted_at order_id, order_total, commission_amount, converted_at, status Sort field
direction string No desc asc, desc Sort direction
per_page integer No 25 1–100 Items per page
page integer No 1 min:1 Page number

Example

curl "https://api.heldsway.com/api/v1/orders?status=pending&sort=order_total&direction=desc&per_page=10" \
  -H "Authorization: Bearer <access_token>"

Success Response — HTTP 200

{
  "success": true,
  "message": "OK",
  "data": {
    "items": [
      {
        "id": 42,
        "order_id": "#135419",
        "affiliate": {
          "id": 7,
          "name": "Salman",
          "referral_code": "SALMAN2026"
        },
        "customer": {
          "name": "Geonwoo Park",
          "email": "geonwoo@example.com"
        },
        "subtotal": "70.00",
        "discount_applied": "0.00",
        "tax": "0.00",
        "order_total": "70.00",
        "commission_rate": "10.00",
        "commission_amount": "7.00",
        "currency": "USD",
        "location_id": "STORE-42",
        "location_name": "Downtown Store",
        "source_domain": "rentmy.com",
        "status": "pending",
        "converted_at": "2026-04-10T14:30:00.000000Z",
        "created_at": "2026-04-10T14:30:00.000000Z"
      },
      {
        "id": 41,
        "order_id": "#135380",
        "affiliate": null,
        "customer": null,
        "subtotal": "140.00",
        "discount_applied": "0.00",
        "tax": "0.00",
        "order_total": "140.00",
        "commission_rate": "0.00",
        "commission_amount": "0.00",
        "currency": "USD",
        "status": "approved",
        "converted_at": "2026-04-08T14:30:00.000000Z",
        "created_at": "2026-04-08T14:30:00.000000Z"
      }
    ],
    "meta": {
      "current_page": 1,
      "per_page": 10,
      "total": 2,
      "last_page": 1
    }
  }
}

Response Fields

Field Type Description
items[].id integer Internal conversion record ID
items[].order_id string External order identifier
items[].affiliate object|null Attributed affiliate (null if unattributed)
items[].affiliate.id integer Affiliate ID
items[].affiliate.name string Affiliate’s display name
items[].affiliate.referral_code string Affiliate’s referral code
items[].customer object|null Customer info (null if no customer data)
items[].customer.name string|null Customer name
items[].customer.email string|null Customer email
items[].subtotal string Pre-discount amount (2 decimal places)
items[].discount_applied string Discount amount
items[].tax string Tax amount
items[].order_total string Gross total
items[].commission_rate string Commission rate (%) applied
items[].commission_amount string Computed commission amount
items[].currency string 3-letter currency code (default USD)
items[].status string pending, approved, rejected, or cancelled
items[].converted_at string|null ISO 8601 timestamp of conversion
items[].created_at string ISO 8601 timestamp of 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

Get Order Stats — GET /v1/orders/stats

Returns aggregated summary statistics for the business’s affiliate-attributed orders. An order counts unless its status is cancelled — pending, approved, rejected and $0 orders all count. Optionally filter by date range. These are the same figures as the stat cards on the business panel’s Orders & Commissions page.

Query Parameters

Parameter Type Required Constraints Description
from date No YYYY-MM-DD or ISO 8601 date-time Start of date range; a bare date starts at 00:00:00 UTC
to date No YYYY-MM-DD or ISO 8601 date-time, must be >= from End of date range; a bare date ends at 23:59:59 UTC

Example

curl "https://api.heldsway.com/api/v1/orders/stats?from=2026-04-01&to=2026-04-15" \
  -H "Authorization: Bearer <access_token>"

Success Response — HTTP 200

{
  "success": true,
  "message": "OK",
  "data": {
    "total_orders": 2,
    "total_revenue": 210.00,
    "total_commission": 14.00,
    "pending_commission": 0.00,
    "approved_commission": 14.00
  }
}

Response Fields

Field Type Description
total_orders integer Number of counted orders: attributed to an affiliate and not cancelled
total_revenue number Sum of each counted order’s revenue: subtotal (or order_total when subtotal is 0 or empty) minus discount_applied, never below 0 per order. Tax and shipping are excluded
total_commission number Sum of commission_amount across the counted orders
pending_commission number Sum of commission_amount for pending orders
approved_commission number Sum of commission_amount for approved orders

Get Order Detail — GET /v1/orders/{id}

Returns the full detail for a single conversion, including line items and click attribution.

Path Parameters

Parameter Type Description
id integer Conversion record ID

Example

curl "https://api.heldsway.com/api/v1/orders/42" \
  -H "Authorization: Bearer <access_token>"

Success Response — HTTP 200

{
  "success": true,
  "message": "OK",
  "data": {
    "id": 42,
    "order_id": "#135380",
    "affiliate": {
      "id": 7,
      "name": "Salman",
      "referral_code": "SALMAN2026",
      "commission_rate": "10.00"
    },
    "customer": {
      "name": "Jane Smith",
      "email": "jane@example.com"
    },
    "subtotal": "140.00",
    "discount_applied": "0.00",
    "tax": "0.00",
    "order_total": "140.00",
    "commission_rate": "10.00",
    "commission_amount": "14.00",
    "currency": "USD",
    "status": "approved",
    "line_items": [
      { "name": "Mountain Bike Rental", "quantity": 1, "price": "140.00" }
    ],
    "ip_address": "192.168.1.100",
    "click": {
      "id": 123,
      "referral_link_id": 45,
      "landing_page": "https://mountainthreads.example.com/bikes",
      "referrer": "https://instagram.com",
      "created_at": "2026-04-08T10:00:00.000000Z"
    },
    "converted_at": "2026-04-08T14:30:00.000000Z",
    "created_at": "2026-04-08T14:30:00.000000Z",
    "updated_at": "2026-04-08T15:00:00.000000Z"
  }
}

Additional Detail Fields

These fields appear only in the detail response (not in the list):

Field Type Description
affiliate.commission_rate string|null Affiliate’s override commission rate (may differ from business default)
line_items array|null Product details from the order
ip_address string|null Customer’s IP address
click object|null Attribution click data (null if direct conversion)
click.id integer Click record ID
click.referral_link_id integer Associated referral link ID
click.landing_page string|null Page URL where the click landed
click.referrer string|null Referring URL
click.created_at string ISO 8601 timestamp of the click
updated_at string ISO 8601 timestamp of last update

Error — HTTP 404

{
  "success": false,
  "error": {
    "code": "NOT_FOUND",
    "message": "Order not found."
  }
}

Approve Order — POST /v1/orders/{id}/approve

Transitions a pending conversion to approved status. The commission is considered owed once approved.

Path Parameters

Parameter Type Description
id integer Conversion record ID

Body Parameters

Field Type Required Constraints Description
notes string No max:1000 Approval notes (stored in audit log)

Example

curl -X POST "https://api.heldsway.com/api/v1/orders/42/approve" \
  -H "Authorization: Bearer <access_token>" \
  -H "Content-Type: application/json" \
  -d '{ "notes": "Verified payment received" }'

Success Response — HTTP 200

{
  "success": true,
  "message": "Order #135419 approved.",
  "data": {
    "id": 42,
    "order_id": "#135419",
    "status": "approved",
    "commission_amount": "7.00",
    "updated_at": "2026-04-15T12:00:00.000000Z"
  }
}

Error — HTTP 409 (Invalid Status Transition)

{
  "success": false,
  "error": {
    "code": "INVALID_STATUS",
    "message": "Only pending conversions can be approved. Current status: approved"
  }
}

Error — HTTP 404

{
  "success": false,
  "error": {
    "code": "NOT_FOUND",
    "message": "Order not found."
  }
}

Reject Order — POST /v1/orders/{id}/reject

Transitions a pending conversion to rejected status. The commission is voided.

Path Parameters

Parameter Type Description
id integer Conversion record ID

Body Parameters

Field Type Required Constraints Description
reason string No max:1000 Rejection reason (stored in audit log)

Example

curl -X POST "https://api.heldsway.com/api/v1/orders/42/reject" \
  -H "Authorization: Bearer <access_token>" \
  -H "Content-Type: application/json" \
  -d '{ "reason": "Fraudulent order - chargeback received" }'

Success Response — HTTP 200

{
  "success": true,
  "message": "Order #135419 rejected.",
  "data": {
    "id": 42,
    "order_id": "#135419",
    "status": "rejected",
    "commission_amount": "7.00",
    "updated_at": "2026-04-15T12:00:00.000000Z"
  }
}

Error — HTTP 409 (Invalid Status Transition)

{
  "success": false,
  "error": {
    "code": "INVALID_STATUS",
    "message": "Only pending conversions can be rejected. Current status: approved"
  }
}

Bulk Approve — POST /v1/orders/bulk-approve

Approves multiple pending conversions in a single request. Non-pending conversions are silently skipped.

Body Parameters

Field Type Required Constraints Description
ids integer[] Yes min:1, max:100, each distinct Conversion IDs to approve

Example

curl -X POST "https://api.heldsway.com/api/v1/orders/bulk-approve" \
  -H "Authorization: Bearer <access_token>" \
  -H "Content-Type: application/json" \
  -d '{ "ids": [42, 43, 44, 45, 46] }'

Success Response — HTTP 200

{
  "success": true,
  "message": "3 order(s) approved.",
  "data": {
    "approved_count": 3,
    "requested_count": 5,
    "skipped_count": 2
  }
}

Response Fields

Field Type Description
approved_count integer Number of conversions actually approved
requested_count integer Total IDs submitted in the request
skipped_count integer IDs that were skipped (non-existent, wrong business, or not pending)

Error — HTTP 422

BulkOrderActionApiRequest rejects the body before the controller runs, so the response is Laravel’s standard validation body (see Error Reference → Validation Errors (422)):

{
  "message": "The ids field is required.",
  "errors": {
    "ids": ["The ids field is required."]
  }
}

Bulk Reject — POST /v1/orders/bulk-reject

Rejects multiple pending conversions in a single request. Non-pending conversions are silently skipped.

Body Parameters

Field Type Required Constraints Description
ids integer[] Yes min:1, max:100, each distinct Conversion IDs to reject
reason string No max:1000 Rejection reason (applied to all, stored in audit log)

Example

curl -X POST "https://api.heldsway.com/api/v1/orders/bulk-reject" \
  -H "Authorization: Bearer <access_token>" \
  -H "Content-Type: application/json" \
  -d '{ "ids": [47, 48], "reason": "Duplicate orders from same session" }'

Success Response — HTTP 200

{
  "success": true,
  "message": "2 order(s) rejected.",
  "data": {
    "rejected_count": 2,
    "requested_count": 2,
    "skipped_count": 0
  }
}

Response Fields

Field Type Description
rejected_count integer Number of conversions actually rejected
requested_count integer Total IDs submitted in the request
skipped_count integer IDs that were skipped

Export Orders — GET /v1/orders/export

Downloads all matching conversions as a CSV file. Same filters as the list endpoint but without pagination — returns all matching records up to 10,000 rows.

Query Parameters

Parameter Type Required Constraints Description
search string No max:255 Search by order ID or affiliate name
status string No pending, approved, rejected, cancelled Filter by status
affiliate_id integer No Valid affiliate ID Filter by affiliate
from date No YYYY-MM-DD or ISO 8601 date-time Start of date range; a bare date starts at 00:00:00 UTC
to date No YYYY-MM-DD or ISO 8601 date-time, must be >= from End of date range; a bare date ends at 23:59:59 UTC

Example

curl "https://api.heldsway.com/api/v1/orders/export?status=approved&from=2026-04-01" \
  -H "Authorization: Bearer <access_token>" \
  -o orders-export.csv

Success Response — HTTP 200

Content-Type: text/csv Content-Disposition: attachment; filename="orders-export-2026-04-15.csv"

Order ID,Affiliate Name,Affiliate Code,Subtotal,Discount,Tax,Order Total,Commission Rate (%),Commission Amount,Currency,Status,Customer Email,Converted At
#135380,Salman,SALMAN2026,140.00,0.00,0.00,140.00,10.00,14.00,USD,approved,jane@example.com,2026-04-08 14:30:00
#135419,,,70.00,0.00,0.00,70.00,0.00,0.00,USD,pending,geonwoo@example.com,2026-04-10 14:30:00

CSV Columns

Column Description
Order ID External order identifier
Affiliate Name Affiliate’s display name (empty if unattributed)
Affiliate Code Affiliate’s referral code (empty if unattributed)
Subtotal Pre-discount amount
Discount Discount applied
Tax Tax amount
Order Total Gross total
Commission Rate (%) Rate applied
Commission Amount Computed commission
Currency 3-letter currency code
Status Conversion status
Customer Email Customer’s email (empty if unavailable)
Converted At Conversion timestamp

Conversion Status Workflow

  ┌─────────┐
  │ pending  │ ← initial state (from SDK tracking)
  └────┬─────┘
       │
  ┌────┴────┐
  ▼         ▼
┌─────────┐ ┌──────────┐
│ approved│ │ rejected │
└─────────┘ └──────────┘

  ┌───────────┐
  │ cancelled │ ← set by system (order cancellation)
  └───────────┘
  • Only pending conversions can be approved or rejected via the API.
  • Attempting to approve/reject a non-pending conversion returns HTTP 409.
  • The cancelled status is set by the system when an order is cancelled — it is not available as an API action.

Error Reference

HTTP Status Error Code Cause
401 UNAUTHORIZED Missing or invalid Bearer token
402 SUBSCRIPTION_REQUIRED The business has no active subscription (see Error Reference → Subscription Required (402))
403 FORBIDDEN Token does not have required scope (orders:read or orders:write)
403 FEATURE_NOT_AVAILABLE GET /v1/orders/export only — the plan does not include CSV export
404 NOT_FOUND Conversion ID does not exist or belongs to a different business
409 INVALID_STATUS Attempted to approve/reject a non-pending conversion
422 — Invalid query parameters or request body. Every orders endpoint validates with a Form Request, so the body is Laravel’s standard validation response with no code (see Error Reference → Validation Errors (422))
429 RATE_LIMIT_EXCEEDED Rate limit exceeded

Rate Limiting

Endpoint Group Limit
Read endpoints (list, stats, show) 120 requests/min
Write endpoints (approve, reject, bulk) 60 requests/min
Export 30 requests/min

Exceeding the limit returns HTTP 429 Too Many Requests with error code RATE_LIMIT_EXCEEDED.