Track Sale
Record an attributed sale and create the partner commission from your backend
Call this endpoint from your server after a payment succeeds to record the conversion and trigger commission creation.
Endpoint
POST https://api.affitor.com/api/v1/track/sale
Authorization: Bearer YOUR_PROGRAM_API_KEY
Content-Type: application/jsonAuthentication
All requests require a program API key sent as a Bearer token in the Authorization header. The API key is found in your program settings in the Affitor dashboard.
Authorization: Bearer YOUR_PROGRAM_API_KEYRequest Fields
Your unique payment identifier. Used for duplicate detection — re-sending the same value returns 409.
Sale amount in the smallest currency unit (e.g. cents for USD). Must be a positive integer.
Your internal customer/user ID, set during the signup tracking step. Used to resolve attribution. At least one of customer_key or click_id must match an existing customer record.
The Affitor click ID (affitor_click_id cookie value). Used as fallback attribution when customer_key is not provided.
ISO 4217 currency code. Defaults to USD.
"payment" (default) or "subscription".
paymentsubscriptionArbitrary line-item detail to store with the sale record.
true if this is a recurring billing charge. Defaults to false.
Your subscription identifier. Required for proper recurring commission attribution.
"monthly", "quarterly", or "annual".
monthlyquarterlyannualYour product identifier. Used for per-product commission policy matching.
Request Body Example
curl -X POST https://api.affitor.com/api/v1/track/sale \
-H "Authorization: Bearer YOUR_PROGRAM_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"transaction_id": "txn_abc123",
"customer_key": "usr_9876",
"amount_cents": 4900,
"currency": "USD",
"sale_type": "payment"
}'Subscription example
{
"transaction_id": "inv_sub_001",
"customer_key": "usr_9876",
"amount_cents": 4900,
"currency": "USD",
"sale_type": "subscription",
"is_recurring": true,
"subscription_id": "sub_stripe_xyz",
"subscription_interval": "monthly",
"product_id": "prod_pro_plan"
}Response
{
"success": true,
"sale_id": 42,
"commission_id": 17,
"message": "Sale tracked successfully"
}| Field | Type | Description |
|---|---|---|
success | boolean | true on success. |
sale_id | integer | ID of the created sale event record. |
commission_id | integer | ID of the created commission record. |
message | string | Human-readable confirmation. |
Re-sending the same transaction_id returns 409 Conflict — Affitor does not create a duplicate sale. This is intentional: you can safely retry on network failure by checking for 409 before treating the call as failed.
A 409 response means the sale was already recorded successfully. Do not retry a 409 — treat it as a successful prior call and continue your payment flow normally.
Error Responses
| Status | When |
|---|---|
400 | transaction_id missing or not a string |
400 | amount_cents missing, not a positive integer |
400 | Neither customer_key nor click_id resolved a customer record |
400 | Customer does not belong to the program identified by the API key |
400 | No partner-program relationship found for the resolved customer |
401 | Missing or malformed Authorization header |
401 | API key does not match any active program |
409 | transaction_id already recorded — duplicate sale |
500 | Commission creation failed internally |
Test Mode
Send additional_data.test_mode: true to create a test sale event without affecting production data. The API key is still required but transaction_id and amount_cents are optional in test mode.
{
"additional_data": {
"test_mode": true
}
}Test mode response:
{
"success": true,
"message": "Test sale event tracked successfully",
"data": {
"eventId": 12,
"programId": 3,
"test_mode": true
}
}