Skip to main content

Overview

Use Affonso’s server-side event endpoints when your backend already knows that something happened and you want Affonso to:
  • resolve the correct referral
  • match the correct incentive rule
  • calculate commissions automatically when applicable
  • advance referral lifecycle state from trusted backend events
  • process full or partial refunds
  • enforce idempotency on retries
  • emit the standard transaction webhooks
This is the recommended integration path for backend-driven affiliate tracking.

Which Endpoint to Use

Use POST /conversions when:
  • you want Affonso to calculate the commission for you
  • you have a billing event, order, invoice, or checkout completion on your server
  • you want retry-safe idempotency with external_event_id
Use POST /events when:
  • you want to send a normalized event from your backend
  • the event may represent a conversion, lead, trial, or milestone
  • you want one endpoint for both revenue and non-revenue lifecycle events
Use POST /conversions/{id}/refund when:
  • you already recorded a conversion in Affonso
  • you need to apply a full or partial refund
  • you want Affonso to update the transaction and commission state for you
Use POST /commissions when:
  • you already know the exact commission amount
  • you are importing historical payouts or backfilling data
  • you need a manual override rather than incentive-based calculation

Canonical Event Model

All Phase 2 server-side endpoints normalize into one internal event model before business logic runs. Shared fields:
  • event_name
  • event_type
  • at least one identifier: referral_id, customer_id, external_user_id, or click_id
  • optional external_event_id for idempotency
  • optional metadata
Conversion events additionally require:
  • sale_amount
  • sale_amount_currency
  • external_event_id
Optional matching fields for conversion events:
  • product_ids
  • price_ids
  • interval
  • is_subscription

Idempotency and Retries

external_event_id is the provider-side idempotency key whenever you want retry-safe ingestion. Use a stable unique identifier from your system, such as:
  • order ID
  • invoice ID
  • checkout session ID
  • payment event ID Behavior by endpoint:
  • POST /conversions stays idempotent on external_event_id
  • POST /events is idempotent when external_event_id is present
  • POST /conversions/{id}/refund is idempotent when external_event_id is present
Reuse the exact same external_event_id when retrying the same upstream event.

Choosing the Identifier

Use the identifier you can trust most in your integration:
  • customer_id: best when the referral is already linked to your internal customer record
  • external_user_id: useful when you sync your application user ID into Affonso
  • click_id: best when converting a specific tracked click into a purchase
  • referral_id: best when you already know the exact referral record to credit

Request Signing

Request signing is optional and non-breaking. When no signing secret is configured, standard Bearer API-key requests continue to work without extra headers.

Environment Variables

  • S2S_REQUEST_SIGNING_SECRET

Required Headers for Signed Requests

  • X-Affonso-Timestamp: Unix timestamp in seconds
  • X-Affonso-Signature: hex HMAC_SHA256(secret, "<timestamp>.<raw_body>")
Replay protection window: 5 minutes.

What Affonso Creates

Conversion event

On a successful conversion, Affonso always records the underlying transaction. If the matched incentive is eligible, Affonso also creates the affiliate earning automatically. If no incentive matches, or if the commission is fully capped, the conversion can still succeed with commission_amount: 0, commission_currency: null, and earning_id: null.

Milestone event

For lead, trial, and milestone events, Affonso updates the referral lifecycle state and may create a lead incentive transaction when your program rules allow it.

Refund event

Refunds reduce the remaining sale amount on the transaction. Partial refunds set sales_status to partial_refunded. Full refunds set sales_status to refunded, and if an affiliate earning exists, its commission amount is reduced proportionally.

Example Flows

Backend purchase

curl -X POST "https://api.affonso.io/v1/conversions" \
  -H "Authorization: Bearer sk_live_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{
    "customer_id": "cust_123",
    "sale_amount": 99.00,
    "sale_amount_currency": "USD",
    "external_event_id": "inv_2026_000145",
    "sales_status": "complete",
    "is_subscription": true,
    "interval": "monthly",
    "price_ids": ["price_monthly_usd"]
  }'
{
  "success": true,
  "data": {
    "id": "com_abc123",
    "referral_id": "ref_456def",
    "affiliate_id": "aff_789ghi",
    "program_id": "prog_123xyz",
    "sale_amount": 99,
    "sale_amount_currency": "USD",
    "commission_amount": 29.7,
    "commission_currency": "USD",
    "status": "ready_for_payment",
    "sales_status": "complete",
    "hold_period_days": null,
    "payment_intent_id": null,
    "invoice_id": null,
    "earning_id": "earn_123abc",
    "earning_type": "direct_commission",
    "external_event_id": "inv_2026_000145",
    "calculation_mode": "auto",
    "matched_incentive_id": "inc_monthly_001",
    "created_at": "2026-06-22T12:00:00.000Z",
    "updated_at": "2026-06-22T12:00:00.000Z"
  }
}

Next Steps

Conversions API Reference

Full request and response field reference for POST /conversions

Events API Reference

Send normalized conversion, lead, trial, and milestone events

Refund Conversion

Apply a full or partial refund to an existing conversion

Manual Commissions

Use the manual endpoint when you need to set the commission amount yourself