Background
⌘K

Server-Side Event Tracking

Send conversions, leads, trials, and milestone events from your backend through one Affonso endpoint.

Silvestro
Written by Silvestro
Updated more than a week ago

Server-Side Event Tracking

Use this guide if your backend needs one Affonso endpoint for both revenue and non-revenue events.

With POST /v1/events, you can send:

  • conversion events for paid purchases
  • lead events for qualified signups
  • trial events for trial starts
  • milestone events for product or lifecycle steps such as onboarding, activation, or KYC completion

If you need the full request and response contract, see the Create Event API docs.

💡 Use POST /v1/events when your backend tracks more than just purchases. If you only need a pure payment conversion flow, POST /v1/conversions is still a good fit.

Before You Start

Make sure you have:

  1. An Affonso API key with write:commissions permission
  2. At least one identifier to match the event: referral_id, customer_id, or external_user_id
  3. A stable upstream event ID for idempotency, especially for conversions
  4. Affiliate tracking already installed on your website

If you need the browser-side attribution setup first, start with How Affiliate Tracking Works and Signup & Lead Tracking.

What This Endpoint Does

Affonso accepts a normalized backend event and decides how to process it based on event_type.

Supported event types

  • conversion for paid sales
  • lead for lead-stage milestones
  • trial for trial starts
  • milestone for non-revenue lifecycle events

Required fields

Every request needs:

  • event_name
  • at least one matching identifier: referral_id, customer_id, or external_user_id

Conversion events also require:

  • sale_amount
  • sale_amount_currency
  • external_event_id

For all technical field details, see the Create Event API docs.

Quick Start

1. Pick the identifier you already control

Use the most stable identifier available in your system:

  • external_user_id if you want to match against the user ID in your own app or system
  • referral_id if you already know the exact Affonso referral
  • customer_id if you want to match against the customer ID from your payment provider or billing system, such as Stripe
  • affonso_id if your existing integration already uses it

Affonso only attributes the event if that identifier resolves to an existing referral in your team. If no referral matches, the request is rejected.

  • Prefer external_user_id when your backend has a stable user ID from your product or app
  • Use referral_id when you already know the Affonso referral ID to credit
  • Use customer_id when you want to match with the customer ID from your payment provider or billing system
  • If your existing integration already uses affonso_id, you can keep using it
  • If you send multiple identifiers, they must resolve to the same referral

2. Send the event from your backend

Endpoint:

POST https://api.affonso.io/v1/events

Headers:

Authorization: Bearer sk_live_your_key_here
Content-Type: application/json

3. Start with a trial or milestone event

This is a simple example for a trial start:

curl -X POST "https://api.affonso.io/v1/events" \
  -H "Authorization: Bearer sk_live_your_key_here" \
  -H "Content-Type: application/json" \
  -d '{
    "event_name": "trial_started",
    "event_type": "trial",
    "customer_id": "cust_123",
    "external_event_id": "evt_trial_123"
  }'

Typical use cases:

  • trial_started
  • demo_booked
  • kyc_passed
  • activation_completed

4. Send conversion events when revenue happens

Use the same endpoint for purchases:

curl -X POST "https://api.affonso.io/v1/events" \
  -H "Authorization: Bearer sk_live_your_key_here" \
  -H "Content-Type: application/json" \
  -d '{
    "event_name": "invoice_paid",
    "event_type": "conversion",
    "customer_id": "cust_123",
    "sale_amount": 99,
    "sale_amount_currency": "USD",
    "external_event_id": "evt_2026_000145",
    "product_ids": ["pro_monthly"],
    "price_ids": ["price_123"],
    "is_subscription": true,
    "interval": "monthly"
  }'

How Responses Work

For event_type: "conversion", Affonso returns a conversion response similar to POST /v1/conversions.

For lead, trial, and milestone, Affonso returns an event-processing result that tells you:

  • which referral was matched
  • whether a commission was created
  • which action was taken
  • the resulting referral status

This makes it practical to use one ingestion surface while still handling revenue and non-revenue events differently in your own backend.

When To Use /v1/events

Choose POST /v1/events when:

  • your backend tracks both purchase and product milestone events
  • you want one endpoint for revenue and non-revenue attribution
  • you need a normalized event API instead of separate custom flows

Choose a different path when:

Best Practices

  • Use a stable external_event_id so retries stay idempotent
  • Send occurred_at if the upstream event happened earlier than delivery time
  • Prefer your own stable customer or user IDs over fragile temporary values
  • Include product_ids, price_ids, interval, and is_subscription on conversion events when available for better incentive matching
  • Keep raw provider IDs in metadata for debugging and reconciliation

Troubleshooting

Event was rejected because no user could be matched

Make sure you send at least one of:

  • referral_id
  • external_user_id
  • customer_id

If you need the full list of alternative field names for referral_id, use the Create Event API docs.

Conversion event fails validation

Make sure your request includes:

  • sale_amount
  • sale_amount_currency
  • external_event_id

Duplicate upstream retries create concern

Reuse the same external_event_id when retrying the exact same event. Affonso uses that value for idempotency.

You need the exact request schema

Use the API reference:

Next Steps

Was this article helpful?

If you still need help, our support team is here for you.

Contact Support
bg

Ready to Scale Your SaaS?

Affonso is the easiest way to launch your own affiliate program. We take care of the technical stuff, so you can focus on growing your business.