Skip to content

API Reference

Server-to-server integration guide for tracking referrals, claims, conversions, and refunds from any platform.

Base URL: https://api-production.advocateloop.com


Authentication

Two authentication methods are supported. Use whichever fits your integration.

Send your API key and brand ID as HTTP headers on every request.

X-API-Key: your-api-key-here
X-Brand-ID: your-brand-uuid-here

Your API key and brand ID are available in the Advocate Loop dashboard under Settings → API.

Option 2: Webhook Signature (for platforms that sign payloads)

For integrations where your platform signs outgoing webhook payloads (e.g., Zapier, custom webhooks), use HMAC-SHA256 signature verification.

Required headers:

X-Brand-ID: your-brand-uuid-here
X-AL-Signature: hmac-sha256-hex-signature
X-AL-Timestamp: unix-timestamp (optional, enables 5-minute replay protection)

How to compute the signature:

  1. Take the raw JSON request body as a string
  2. Compute HMAC-SHA256 using your API key as the secret
  3. Hex-encode the result
  4. Send it in the X-AL-Signature header
const crypto = require('crypto');
const body = JSON.stringify(payload);
const signature = crypto
.createHmac('sha256', YOUR_API_KEY)
.update(body)
.digest('hex');

The webhook signature method is currently only available on POST /api/v1/convert (see the Convert endpoint below). All other endpoints use API key authentication.


Endpoints

Track Visit (Click)

Record when a visitor clicks a referral link on your site.

POST /api/v1/track/visit
Auth: API Key

Request body:

FieldTypeRequiredDescription
referral_codestringYesThe referral code from the URL
visitor_idstringNoVisitor identifier (UUID). If omitted, one is generated
existing_codestringNoReferral code already stored on the visitor’s device
share_channelstringNoTraffic source (e.g., sms, email, facebook). Typically from utm_source
landing_pagestringNoThe full URL the visitor landed on

Response (200):

{
"success": true,
"data": {
"store_code": true,
"clear_existing": false,
"code": "V2AVMRDJ",
"referrer_first_name": "Sarah",
"visitor_id": "729979f7-447b-4c81-a885-e863aa94f7e4"
}
}

Track Claim

Record when a customer uses or claims a referral discount. Creates a claim record with status: pending.

POST /api/v1/track/claim
Auth: API Key

Request body:

FieldTypeRequiredDescription
referral_codestringYesThe referral code being claimed
email or customer_emailstringYesCustomer’s email address
visitor_idstringNoVisitor identifier from click tracking
name or customer_namestringNoCustomer’s name
order_idstringNoOrder/transaction identifier
raw_valuenumberNoOrder value before discount
claim_valuenumberNoOrder value after discount
discount_valuenumberNoDiscount amount configured
discount_typestringNopercentage, fixed, or custom
type or claim_typestringNoreferral (default) or advocate
productsarrayNoProducts in the order. See Products Array section below
coupons_appliedarrayNoCoupons used: [{ code, discount_amount, discount_tax }]
metadataobjectNoAny additional data you want to store

Response (201):

{
"success": true,
"data": {
"id": 42,
"claim_id": 42,
"referral_code": "V2AVMRDJ",
"status": "pending",
"discount_applied": 5.70,
"claim_value": 51.30
}
}

Track Conversion

Record a completed order/payment. This is the most important endpoint — it records the conversion and credits the advocate’s reward.

Call this only after payment succeeds, not at checkout time.

POST /api/v1/track/conversion
Auth: API Key

Request body:

FieldTypeRequiredDescription
email or customer_emailstringYesCustomer’s email address
order_idstringYesUnique order/transaction identifier
order_valuenumberYesFinal order value (after discounts)
referral_codestringNoReferral code. If omitted, the API resolves it from coupons_applied or prior attribution
visitor_idstringNoVisitor identifier. Helps with attribution but not required for cross-device flows
claim_idintegerNoExplicit claim ID to link. Usually resolved automatically via email
referrer_reward_paidnumberNoReward amount paid to the referrer
referee_reward_paidnumberNoReward amount given to the customer
discount_valuenumberNoDiscount configuration value
discount_typestringNopercentage, fixed, or custom
typestringNoreferral (default) or advocate
productsarrayNoProducts in the order. See Products Array section below
coupons_appliedarrayNoAll coupons used: [{ code, discount_amount, discount_tax }]
sourcestringNoSource identifier (e.g., shopify, custom, api)
statusstringNoOverride status. Default: completed
metadataobjectNoAny additional data

Response (201):

{
"success": true,
"data": {
"id": 15,
"status": "completed",
"order_value": 51.30,
"discount_applied": 5.70,
"total_discount": 5.70,
"order_subtotal": 57.00,
"claim_id": 42
}
}

Sending attribution data:

Provide as much identifying information as you have. For server-to-server integrations, sending customer_email along with either coupons_applied or referral_code is typically sufficient.


Track Refund

Record a full or partial refund. Updates the claim and conversion status.

POST /api/v1/track/refund
Auth: API Key

Request body:

FieldTypeRequiredDescription
order_idstringYes*Order identifier. Used to find the conversion to update
refund_amountnumberYesAmount being refunded
is_full_refundbooleanYesWhether this is a complete refund
conversion_idintegerNoExplicit conversion ID (alternative to order_id lookup)
claim_idintegerNoExplicit claim ID (alternative to order_id lookup)
referral_codestringNoReferral code (for logging)
refund_idstringNoYour platform’s refund identifier
total_refundednumberNoCumulative refund total
order_totalnumberNoOriginal order total
refund_reasonstringNoReason for the refund
new_statusstringNoOverride status. Default: refunded (full) or partial_refund (partial)
sourcestringNoSource identifier
metadataobjectNoAny additional data

*Either order_id or conversion_id is required so the API can find the record to update.

Response (200):

{
"success": true,
"data": {
"status": "refunded",
"claim_updated": true,
"conversion_updated": true,
"claim_id": 42,
"conversion_id": 15
}
}

Check Eligibility

Check whether a customer is eligible for a referral discount before applying it.

POST /api/v1/track/check-eligibility
Auth: API Key

Request body:

FieldTypeRequiredDescription
referral_codestringYesThe referral code to check
customer_emailstringYesCustomer’s email address
typestringNoreferral or advocate

Response (200, eligible):

{
"eligible": true
}

Response (200, not eligible):

{
"eligible": false,
"error": "already_redeemed",
"message": "This customer has already used a referral discount."
}

Convert (Webhook)

Simplified claim creation for external webhook sources (Calendly, Zapier, custom integrations). Uses webhook signature authentication instead of API key.

POST /api/v1/convert
Auth: Webhook Signature

Request body:

FieldTypeRequiredDescription
referral_codestringYesThe referral code
emailstringYesCustomer’s email address
valuenumberNoTransaction value (before discount). Default: 0
customer_namestringNoCustomer’s name
metadataobjectNoAny additional data

Response (201):

{
"success": true,
"data": {
"claim_id": 43,
"referral_code": "V2AVMRDJ",
"raw_value": 99.00,
"claim_value": 93.30,
"discount_applied": 5.70,
"created_at": "2026-04-14T20:00:00.000Z"
}
}

Duplicate protection: Repeat submissions of the same claim are prevented. If a duplicate is detected, the endpoint returns 409 Conflict with the existing claim_id.


Common Integration Patterns

Products Array

The products field accepted by /track/claim and /track/conversion is a JSON array of product objects. Any fields you send are stored, but the dashboard uses these specific fields for the “Top Products by Revenue” report:

FieldAliasesTypeDefaultUsed for
nametitle, product_namestring”Unknown Product”Product identification in reports
quantityqtyinteger1Units sold calculation
pricetotal, line_totalnumber0Revenue calculation (price × quantity)

Additional fields like sku, variant, category, size, image_url, etc. are preserved in the database but not actively processed by the dashboard. Include them if you want the data available for future reporting.

Example:

{
"products": [
{
"name": "Classic T-Shirt",
"price": 29.99,
"quantity": 2,
"sku": "TSH-001",
"variant": "Large / Black",
"category": "Apparel"
},
{
"name": "Canvas Tote",
"price": 15.00,
"quantity": 1,
"sku": "BAG-010"
}
]
}

Shopify (or any e-commerce platform without a plugin)

On referral link click (storefront JS or server-side):

POST /api/v1/track/visit
{ "referral_code": "V2AVMRDJ", "landing_page": "https://yourstore.com/?ref=V2AVMRDJ" }

At checkout (before payment, to create the claim):

POST /api/v1/track/claim
{
"referral_code": "V2AVMRDJ",
"customer_email": "buyer@example.com",
"order_id": "ORD-12345",
"raw_value": 57.00,
"coupons_applied": [{ "code": "V2AVMRDJ", "discount_amount": 5.70 }],
"products": [
{ "name": "Classic T-Shirt", "price": 29.99, "quantity": 1, "sku": "TSH-001" },
{ "name": "Canvas Tote", "price": 27.01, "quantity": 1, "sku": "BAG-010" }
]
}

After payment succeeds (webhook from payment processor):

POST /api/v1/track/conversion
{
"customer_email": "buyer@example.com",
"order_id": "ORD-12345",
"order_value": 51.30,
"coupons_applied": [{ "code": "V2AVMRDJ", "discount_amount": 5.70 }],
"products": [
{ "name": "Classic T-Shirt", "price": 29.99, "quantity": 1, "sku": "TSH-001" },
{ "name": "Canvas Tote", "price": 27.01, "quantity": 1, "sku": "BAG-010" }
]
}

On refund (webhook from payment processor):

POST /api/v1/track/refund
{
"order_id": "ORD-12345",
"refund_amount": 51.30,
"is_full_refund": true
}

Booking / SaaS / Service Business

For businesses without a traditional checkout (appointment booking, subscriptions, service sign-ups), you typically need just the claim and conversion:

When customer signs up with a referral code:

POST /api/v1/track/claim
{
"referral_code": "V2AVMRDJ",
"customer_email": "client@example.com",
"customer_name": "Jane Smith",
"raw_value": 150.00
}

When payment is confirmed (immediately or later):

POST /api/v1/track/conversion
{
"customer_email": "client@example.com",
"order_id": "BOOKING-789",
"order_value": 142.50,
"referral_code": "V2AVMRDJ"
}

Zapier / Make / n8n (webhook-based)

Use the /api/v1/convert endpoint with webhook signature authentication. This is simpler than the full claim + conversion flow and suitable for integrations where you just need to record that a referral happened.

Zapier setup:

  1. Trigger: your platform event (new booking, form submission, etc.)
  2. Action: Webhooks by Zapier → POST
  3. URL: https://api-production.advocateloop.com/api/v1/convert
  4. Headers: X-Brand-ID, X-AL-Signature, X-AL-Timestamp
  5. Body: { "referral_code": "...", "email": "...", "value": ... }

See the Authentication section above for how to compute the signature.


Error Handling

All endpoints return JSON with a success field.

Success responses:

{ "success": true, "data": { ... } }

Error responses:

{ "success": false, "error": "Human-readable error message" }

HTTP status codes:

CodeMeaning
200Success
201Created (new claim or conversion)
400Bad request (missing required fields)
401Authentication failed (bad API key or missing headers)
403Forbidden (brand ID doesn’t match API key)
404Not found (invalid referral code)
409Conflict (duplicate claim within 24 hours)
429Rate limited
500Internal server error

Rate Limits

EndpointLimit
/track/visit100/min per IP
/track/claim20/hour per IP
/track/conversion20/hour per IP
/track/refund20/hour per IP
/track/check-eligibility100/min per IP
/convert (webhook)100/min per IP

Rate-limited responses return 429 Too Many Requests.


Testing

Use a test brand and real API key from your dashboard. All endpoints work identically in test and production — there’s no sandbox mode. To clean up test data, delete the relevant rows from your database.

Quick test with curl:

Terminal window
# Record a click
curl -X POST https://api-production.advocateloop.com/api/v1/track/visit \
-H "Content-Type: application/json" \
-H "X-API-Key: your-api-key" \
-H "X-Brand-ID: your-brand-id" \
-d '{"referral_code": "TESTCODE"}'
# Create a claim
curl -X POST https://api-production.advocateloop.com/api/v1/track/claim \
-H "Content-Type: application/json" \
-H "X-API-Key: your-api-key" \
-H "X-Brand-ID: your-brand-id" \
-d '{"referral_code": "TESTCODE", "customer_email": "test@example.com", "raw_value": 100}'
# Record a conversion
curl -X POST https://api-production.advocateloop.com/api/v1/track/conversion \
-H "Content-Type: application/json" \
-H "X-API-Key: your-api-key" \
-H "X-Brand-ID: your-brand-id" \
-d '{"customer_email": "test@example.com", "order_id": "TEST-001", "order_value": 95.00, "referral_code": "TESTCODE"}'