logo
Conversions

Send lead and sale events from your server

Record a sign-up and a purchase against the click that produced them — request bodies, the click id, amounts in cents, and idempotency.

Avatar for undefined
CodeQR Team
Equipe de Conteúdo

Two requests do the whole job: one when someone identifies themselves, one when they pay. Both run on your server, with a secret API key, and both quote the click id that brought the person in.

Availability

  • Plan: Pro and above, or the 14-day trial.
  • Where: your backend. Create the key under SettingsAPI Keys.

Before you start

  • Conversion tracking must be on for the link or QR code — Set up conversion tracking on your website.
  • Have the click id available. It arrives as ?cq_id=… on your destination URL and is stored in the cq_id cookie.
  • Decide on a stable identifier for each customer in your own system. It ties the sale to the lead later.

Record a lead

Call this when a visitor becomes identifiable — sign-up, form submission, trial start.

curl -X POST https://api.codeqr.io/track/lead \
  -H "Authorization: Bearer codeqr_xxxxxxxxxxxxxxxxxxxxxxxx" \
  -H "Content-Type: application/json" \
  -d '{
    "clickId": "qcdyQHsX1oajEock",
    "eventName": "Sign up",
    "customerExternalId": "user_123",
    "customerName": "Ada Lovelace",
    "customerEmail": "ada@example.com"
  }'

The response confirms the click and returns the customer CodeQR now knows:

{
  "click": { "id": "qcdyQHsX1oajEock" },
  "customer": {
    "id": "cmszcuwyr0003fdlpmoy3814u",
    "name": "Ada Lovelace",
    "email": "ada@example.com",
    "externalId": "user_123",
    "country": "BR"
  }
}
  • clickId — read it from the cq_id cookie or from the query parameter. An empty string is allowed: CodeQR then looks for an existing customer with the same customerExternalId and reuses their click.
  • eventName — free text, up to 255 characters. It is also the handle a later sale can point at.
  • customerExternalId — required, your own id. Everything the customer does afterward attaches to it.

Record a sale

curl -X POST https://api.codeqr.io/track/sale \
  -H "Authorization: Bearer codeqr_xxxxxxxxxxxxxxxxxxxxxxxx" \
  -H "Content-Type: application/json" \
  -d '{
    "customerExternalId": "user_123",
    "amount": 4990,
    "currency": "usd",
    "eventName": "Purchase",
    "paymentProcessor": "stripe",
    "invoiceId": "INV-001"
  }'
{
  "eventName": "Purchase",
  "customerId": "user_123",
  "amount": 4990,
  "paymentProcessor": "stripe",
  "invoiceId": "INV-001",
  "currency": "usd",
  "metadata": null
}
  • amount is in the smallest unit of the currency — 4990 is $49.90. This is the single most common mistake, and it is silent: a sale of 49.90 records 49 cents.
  • paymentProcessor accepts stripe, shopify, polar, paddle, revenuecat, custom and manual.
  • invoiceId makes the call idempotent. Sending the same invoice twice returns the same response and does not double-count — which matters because payment webhooks retry.
  • leadEventName attaches the sale to a specific earlier lead instead of the most recent one.

Sales that arrive before the lead

You do not have to send them in order. A sale for a customer CodeQR has never seen creates the lead implicitly, provided the sale carries enough to find the click — the customerExternalId you used earlier, or a clickId.

Verify it works

Ask the link for its counters a few seconds later:

curl -sS "https://api.codeqr.io/links/info?domain=go.example.com&key=summer" \
  -H "Authorization: Bearer codeqr_xxxxxxxxxxxxxxxxxxxxxxxx"
{ "key": "summer", "clicks": 1, "leads": 1, "sales": 1, "saleAmount": 4990 }

Then open Customers and select the person: the panel shows the click, the lead and the sale in order, with the amount.

Troubleshooting

The call returns 404

The clickId does not exist or has expired. Confirm the value you read from the cookie, and remember that without conversion tracking the click id only lives for an hour.

The call returns 200 and nothing is recorded

A lead with an empty clickId and no matching customer is accepted and discarded — there is nothing to attribute it to. Send the click id, or send a customerExternalId CodeQR has already seen.

The revenue is a hundred times too small

amount is in cents. 4990, not 49.90.

The same sale counted twice

The two calls used different invoiceId values, or none. Idempotency is keyed on that field and holds for seven days.

The sale does not appear in the Events tab

Listing sale events currently fails. Use Customers, or the link counters shown above; both are correct.

Related articles