Skip to content

REST API

The AdvocateLoop API lets you record claims, conversions, refunds, and visits with a simple HTTP POST — from your own backend, or from any tool that can send an HTTP request.

Prefer a no-code tool? See Zapier or Make; both send events through this same API.

What you’ll need

Before configuring anything, gather two values from your AdvocateLoop dashboard:

  • API Key — found under Settings → API Keys. Keep this secret; treat it like a password.
  • Brand ID — found alongside the API key on the same page.

You’ll send both as HTTP headers on every request.

Plan tiers

Some event types are available on all plans; others require Premier:

EventStarterGrowthPremier
Conversions (/track/conversion)
Refunds (/track/refund)
Claims (/track/claim)
Visits (/track/visit)

If you send a Premier-only event type on a lower-tier plan, the API returns a 403 response with a clear message.

The basics

Every request follows the same shape:

  • URL: https://api.advocateloop.com/api/v1/track/<event> (e.g. /api/v1/track/conversion)
  • Method: POST
  • Headers:
    • Content-Type: application/json
    • X-API-Key: <your API key>
    • X-Brand-ID: <your brand ID>
  • Body: JSON payload (shape depends on the event type — see below)

If the request succeeds, you’ll get a 200 response with a JSON body like:

json
{ "success": true, "data": { /* event-specific details */ } }

If something goes wrong, you’ll get a 4xx response with an explanation:

json
{ "success": false, "error": "what went wrong" }

Recording a conversion

Use this when someone completes a purchase or other tracked outcome that should count against a referral.

Request

http
POST https://api.advocateloop.com/api/v1/track/conversion
Content-Type: application/json
X-API-Key: <your API key>
X-Brand-ID: <your brand ID>
{
"customer_email": "buyer@example.com",
"customer_name": "Jane Doe",
"order_id": "ORD-12345",
"order_total": 108.00,
"tax": 8.00,
"shipping": 10.00,
"discount": 5.00,
"referral_code": "JOHN123",
"items": [
{
"name": "Vitamin C Serum",
"quantity": 2,
"unit_price": 32.00,
"sku": "VITC-30",
"category_path": ["Skincare", "Serums"]
},
{ "name": "Gift Wrapping", "quantity": 1, "unit_price": 4.00 }
]
}

Fields

FieldRequiredNotes
customer_emailyesCustomer’s email address
order_totalyesWhat the customer actually paid — items + tax + shipping, after discounts
tax, shipping, discountyesUse 0 if not applicable
customer_namenoCustomer’s name
order_idnoYour internal order identifier, for cross-referencing
referral_codenoInclude if you know it
itemsnoLine items in the order. Fields below.

Each entry in items:

FieldRequiredNotes
nameyesItem or service name
quantitynoUnits. Defaults to 1
unit_pricenoPrice per unit. Or send line_total for the line’s total
skunoSKU, plan code, or service code
category_pathnoOrdered category path, top level first — e.g. ["Skincare", "Serums"]
image_urlnoImage URL for the item

Available on all plans.

Recording a refund

Use this when an order is refunded (in full or in part) so the conversion is updated accordingly.

Request

http
POST https://api.advocateloop.com/api/v1/track/refund
Content-Type: application/json
X-API-Key: <your API key>
X-Brand-ID: <your brand ID>
{
"order_id": "ORD-12345",
"refund_amount": 50.00,
"refund_reason": "Customer changed mind on one item"
}

Fields

FieldRequiredNotes
order_idone of¹The order_id from the original conversion
conversion_idone of¹AdvocateLoop conversion ID — an alternative way to identify the conversion
claim_idone of¹Associated claim ID — another alternative identifier
refund_amountnoThe amount refunded in this transaction. Omit for a full refund of the remaining amount.
refund_idnoYour refund identifier, for cross-referencing
refund_reasonnoFree-text reason for the refund

¹ Provide at least one of order_id, conversion_id, or claim_id to identify the conversion.

Refunds don’t include an items array.

Available on all plans.

Recording a claim — Premier only

Use this when a customer first claims a referral (signs up, requests a discount code, etc.) from a system that captures sign-ups outside the widget. Most integrations won’t need it.

Request

http
POST https://api.advocateloop.com/api/v1/track/claim
Content-Type: application/json
X-API-Key: <your API key>
X-Brand-ID: <your brand ID>
{
"referral_code": "JOHN123",
"email": "newuser@example.com",
"name": "Sam Smith",
"phone": "+1-555-0100"
}

Fields

FieldRequiredNotes
referral_codeyesThe code being claimed
emailyesThe new user’s email
namenoDisplay name
phonenoContact phone
itemsnoLine items, same fields as the conversion items above

Premier plan only.

Recording a visit — Premier only

Track a click on a referral link from an external system — e.g. logging clicks from a custom email tool. Most integrations won’t need it.

Request

http
POST https://api.advocateloop.com/api/v1/track/visit
Content-Type: application/json
X-API-Key: <your API key>
X-Brand-ID: <your brand ID>
{
"referral_code": "JOHN123",
"landing_page": "https://example.com/products/widget",
"utm_source": "newsletter",
"utm_medium": "email",
"utm_campaign": "spring-sale"
}

Premier plan only.

Sending from your backend

If you’re sending from your own server (Node, Python, PHP, Ruby, anything that can do HTTP), it’s just a POST with the headers and body above. There’s no SDK — the API is small enough that direct HTTP is the simplest path.

Node.js example

javascript
const response = await fetch('https://api.advocateloop.com/api/v1/track/conversion', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-API-Key': process.env.ADVOCATELOOP_API_KEY,
'X-Brand-ID': process.env.ADVOCATELOOP_BRAND_ID
},
body: JSON.stringify({
customer_email: 'buyer@example.com',
order_id: 'ORD-12345',
order_total: 108.00,
tax: 8.00,
shipping: 10.00,
discount: 5.00,
referral_code: 'JOHN123'
})
});
const result = await response.json();
if (!result.success) {
console.error('Failed to record conversion:', result.error);
}

Python example

python
import requests
import os
response = requests.post(
'https://api.advocateloop.com/api/v1/track/conversion',
headers={
'Content-Type': 'application/json',
'X-API-Key': os.environ['ADVOCATELOOP_API_KEY'],
'X-Brand-ID': os.environ['ADVOCATELOOP_BRAND_ID']
},
json={
'customer_email': 'buyer@example.com',
'order_id': 'ORD-12345',
'order_total': 108.00,
'tax': 8.00,
'shipping': 10.00,
'discount': 5.00,
'referral_code': 'JOHN123'
}
)
result = response.json()
if not result.get('success'):
print(f"Failed: {result.get('error')}")

Common issues

“401 Unauthorized” / “Invalid API key” — double-check the X-API-Key header value. Make sure there’s no leading/trailing whitespace and that you’re using the key from the right environment (production vs sandbox if you have separate keys).

“403 Feature not available” on claim/visit — these event types require Premier. Either upgrade your plan, or restructure your integration to use conversions/refunds (which are available on all plans).

“400 Bad Request” with field-specific error — the API tells you which field is missing or invalid. Read the error field of the response.

Numbers arriving as strings — common with some no-code HTTP tools. JSON numbers must not be quoted. If order_total: "108.00" shows up in your request body, your tool is escaping the number. Check your tool’s settings for “data pass-through” or “raw JSON” options.

Webhook fires multiple times — most automation tools retry failed deliveries. Use the order_id field for conversions: if you send the same order_id twice, AdvocateLoop won’t double-count it.

Security best practices

  • Treat your API key like a password. Don’t commit it to source control. Don’t share it in support tickets unless explicitly asked (and rotate it after).
  • Use HTTPS. All AdvocateLoop endpoints require it; HTTP requests are rejected.
  • Rotate keys if you suspect a leak or when a team member with access leaves.
  • Limit access. Give each integration its own API key if you can, so you can revoke one without breaking others.