Vendor API

Connect your platform to AffSpace and track affiliate-driven sales automatically.

Accurate Attribution

Every sale traced to the affiliate who drove it

Real-time Data

See conversions the moment they happen

Automated Payouts

Affiliates paid based on tracked sales

Quick Start

1

Capture the click_id — Save the click_id URL parameter when visitors arrive from affiliate links.

2

Report conversions — POST to /api/v1/conversions when they purchase.

Authentication

Get your API key from the Integration page. Include it in every request:

X-API-Key: your_api_key
# Alternative
Authorization: Bearer your_api_key

Report Conversions

POST/api/v1/conversionsor/pb

Send conversion data to AffSpace when a customer completes a purchase or signs up. The /api/v1/conversions endpoint is preferred for new integrations. The /pb endpoint is legacy but also supports GET requests with query parameters for systems that don't support POST.

Request Body

ParameterDescription
offer_coderequiredYour offer code from the AffSpace dashboard
click_idThe click_id captured when the customer arrived (from the URL parameter). For test mode, prefix with 'test_'.
txidYour order/transaction ID. Prevents duplicate tracking if you send the same conversion twice.
customer_idCustomer identifier. Required for CPA deduplication.
event_type"purchase" or "lead" (defaults to "purchase")
amountSale amount in dollars, e.g. "149.99". Required for CPS/RevShare offers.
currencyCurrency code (USD, EUR, GBP, CAD, AUD). Must match offer currency if provided.

Example Request

curl -X POST "https://your-site.convex.site/api/v1/conversions" \
-H "X-API-Key: your_api_key" \
-H "Content-Type: application/json" \
-d '{
"offer_code": "MYOFFER123",
"click_id": "0M8K2L9P5QRS",
"txid": "ORDER-98765",
"customer_id": "cust_12345",
"amount": "149.99",
"currency": "USD"
}'

Response

{
"success": true,
"data": {
"tracked": true,
"conversionId": "conv_x7k9m2p4",
"status": "pending",
"currency": "USD"
}
}

Understanding Commission Types

TypeHow it worksRequired fields
CPA

Cost Per Action

Fixed amount per conversion, regardless of sale value.e.g., $30 per signup
customer_id

Prevents duplicate payouts

amount

Sale value for payout calculation

CPS

Cost Per Sale

Percentage of each sale value.e.g., 15% of order totalamount

Sale value used to calculate payout

RevShare

Revenue Share

Ongoing percentage for recurring revenue.e.g., 20% of subscription paymentsamount

Payment amount being shared

Always submit the full sale value in amount — AffSpace calculates referral commissions automatically based on your offer terms.

Duplicate Prevention

Include txid (your order ID) to prevent double-tracking on retries. Duplicate txids are acknowledged but not re-tracked.

List Conversions

GET/api/v1/conversions

Retrieve your conversion history with filters for reconciliation and reporting.

Query Parameters

ParameterDescription
offer_codeFilter by specific offer
statuspending, approved, rejected, reversed
start_dateUnix timestamp in milliseconds
end_dateUnix timestamp in milliseconds
limitResults per page (max 500)
cursorPagination cursor

Response

{
"success": true,
"data": [
{
"id": "conv_x7k9m2p4",
"offerCode": "MYOFFER123",
"vendorTxId": "ORDER-98765",
"currency": "USD",
"saleAmountCents": 14999,
"advertiserPayoutCents": 3000,
"status": "approved",
"createdAt": 1706234567890
}
],
"meta": { "pagination": { "hasMore": true, "nextCursor": "..." } }
}

Get Conversion

GET/api/v1/conversions/{id}

Get details for a specific conversion.

Response

{
"success": true,
"data": {
"id": "conv_x7k9m2p4",
"offerCode": "MYOFFER123",
"vendorTxId": "ORDER-98765",
"currency": "USD",
"saleAmountCents": 14999,
"advertiserPayoutCents": 3000,
"status": "approved",
"createdAt": 1706234567890
}
}

Get Statistics

GET/api/v1/stats

Aggregated performance data across your offers — clicks, conversions, revenue, and conversion rates.

Query Parameters

ParameterDescription
offer_codeFilter to specific offer
start_dateStart of range (default: 30 days ago)
end_dateEnd of range (default: now)
group_byday, week, or month for time series

Response

{
"success": true,
"data": {
"summary": {
"totalClicks": 12500,
"totalConversions": 487,
"approvedConversions": 412,
"totalRevenueCents": 1236000,
"conversionRate": "3.90"
},
"byOffer": [
{
"offerCode": "MYOFFER123",
"offerName": "My Product Offer",
"currency": "USD",
"clicks": 5000,
"conversions": 200,
"revenueCents": 600000
}
],
"timeSeries": [
{ "date": "2024-01-25", "clicks": 450, "conversions": 18 }
]
}
}

List Offers

GET/api/v1/offers

View all your offers with their status and payout configuration.

Query Parameters

ParameterDescription
statuspublished, paused, draft, archived
limitResults per page (max 100)
cursorPagination cursor

Response

{
"success": true,
"data": [
{
"code": "MYOFFER123",
"name": "My Product Offer",
"status": "published",
"currency": "USD",
"commissionType": "cpa",
"payoutTerms": { "advertiserPayoutCents": 3000 }
}
]
}

Get Offer

GET/api/v1/offers/{code}

Get full details for a specific offer by its code.

Response

{
"success": true,
"data": {
"code": "MYOFFER123",
"name": "My Product Offer",
"status": "published",
"currency": "USD",
"primaryUrl": "https://...",
"payoutTerms": { "advertiserPayoutCents": 3000 }
}
}

Get Profile

GET/api/v1/profile

Your vendor account information.

Response

{
"success": true,
"data": {
"companyName": "Acme Inc",
"contactEmail": "team@acme.com",
"status": "approved",
"hasApiKey": true
}
}

Create Test Session

POST/api/v1/test-sessions

Generate a test click_id to validate your integration without creating real conversions or triggering payouts.

Request Body

ParameterDescription
offer_coderequiredOffer to test

Response

{
"success": true,
"data": {
"testClickId": "test_0M8K2L9P5QRS",
"sessionToken": "abc123...",
"expiresAt": 1706234867890
}
}

Get Test Session

GET/api/v1/test-sessions/{token}

Check validation results after sending a test conversion.

Response

{
"success": true,
"data": {
"status": "received",
"validation": { "signatureValid": true, "fieldsValid": true }
}
}

Health Check

GET/health

Returns the API health status. Does not require authentication.

Response

{
"status": "ok",
"timestamp": 1706234567890
}

Error Handling

All errors return a consistent format:

{
"success": false,
"error": {
"code": "VALIDATION_ERROR",
"message": "Click not found"
}
}

Error Codes

CodeStatusDescription
UNAUTHORIZED401API key required
INVALID_API_KEY401API key is invalid
VALIDATION_ERROR400Invalid request — see message for details
NOT_FOUND404Resource not found
RATE_LIMITED429Too many requests — check Retry-After header
INTERNAL_ERROR500Server error

Conversion Validation Errors

These return status 400 with code VALIDATION_ERROR

MessageCause
Missing offer_codeoffer_code not provided
Offer not foundoffer_code doesn't match any offer
Offer not activeOffer is paused, draft, or archived
Click not foundclick_id doesn't match any tracked click
customer_id required for CPA offersCPA offer but no customer_id
amount required for CPS/RevShare/percentage offersPercentage-based payout but no amount
amount must be positiveamount is 0 or negative
Click does not belong to this offerclick_id was for a different offer

Acknowledged but Not Tracked

These return success: true with tracked: false. Your integration is working — the conversion just doesn't qualify for additional payout.

{
"success": true,
"tracked": false,
"reason": "cpa_customer_limit",
"message": "Conversion received. This customer already converted..."
}
ReasonExplanation
cpa_customer_limitCustomer already converted under this CPA offer
cpa_click_limitClick already converted under this CPA offer
duplicate_txidConversion already recorded with this transaction ID

Rate Limits

Per API key. Check Retry-After header if limited.

EndpointLimit
GET endpoints100/min
POST endpoints (except conversions)30/min
GET /api/v1/stats20/min
POST /api/v1/conversions, POST /pb1,000/min