Skip to content

Revenue tracking API ​

Documentation for Linkrunner Revenue Tracking API

Deprecated for app payments

POST /capture-payment is deprecated for app payments. It keeps working for existing integrations, but new integrations should send app payments through /capture-event. Website payments still use /capture-payment, see Website payments. See Migrate payments to in-app events.

Revenue is stored for all users, including organic ones. Payments from users with no matching click are stored without campaign attribution. Each request must identify the user with user_id or install_instance_id. You can verify your events are being captured on the Events page.

Use Test Custom Events and Payments to verify event classification, payment fields, and deduplication.

To track payments from your app, and for how each status affects revenue and ad networks, see Track payments.

Base URL ​

https://api.linkrunner.io/api/v1

Authentication ​

Generate your server code from https://dashboard.linkrunner.io/settings?s=data-apis

In the request header add the below attribute:

linkrunner-key: YOUR-SERVER-KEY

Capture a payment ​

Send the payment to the capture-event endpoint with amount, payment_id, and currency at the top level. event_name becomes the payment type you see in reports, so use a name that describes the payment, such as purchase_completed or SUBSCRIPTION_RENEWED.

event_name is stored exactly as you send it. To keep existing event mappings, reports, and affiliate templates working, send an old payment type in uppercase, exactly as before, such as FIRST_PAYMENT, SUBSCRIPTION_RENEWED, or DEFAULT. A different spelling such as first_payment is a new payment type. Any other name is also stored exactly as sent, and you need to add a mapping for it in the dashboard before it reaches ad networks. See Old payment types for the full list.

POST: /capture-event

Request Body ​

json
{
  "event_name": "purchase_completed",
  "amount": 250.96,
  "payment_id": "ORD-12345",
  "currency": "USD",
  "user_id": "user_12345"
}
ParameterTypeDescription
event_namestringRequired. Name of the payment, stored as the payment type
amountnumberRequired for a payment. Zero or more. A numeric string is also accepted
payment_idstringRequired for a payment. Your unique transaction ID
currencystringRequired for a payment. 3-letter ISO 4217 code, for example USD or INR
statusstringOptional. Defaults to PAYMENT_COMPLETED
user_idstringRequired unless install_instance_id is sent. Links the payment to your user. The SDKs always send it with a payment, so send it whenever you have it
install_instance_idstringRequired unless user_id is sent. Linkrunner's ID for the install
event_dataobjectOptional. Additional data, such as ecommerce fields
client_ip_addressstringOptional. See End-user IP address

Send amount, payment_id, and currency together. If you send none of them, or only one or two, the request is stored as a custom event, not a payment. An amount inside event_data does not make the event a payment.

Deduplication: Use a unique payment_id for each transaction. Retrying a request with the same payment_id, event_name, and status does not create a second payment, and the API still returns 200.

Payment status ​

  • PAYMENT_INITIATED: Payment has been initiated
  • PAYMENT_COMPLETED: Payment completed successfully
  • PAYMENT_FAILED: Payment attempt failed
  • PAYMENT_CANCELLED: Payment was cancelled

If status is omitted, it defaults to PAYMENT_COMPLETED. Only PAYMENT_COMPLETED payments are sent to ad networks. See Payment status for what each status does in reports and how to track a payment lifecycle.

End-user IP address ​

These calls come from your server, so Linkrunner never sends your server's IP to ad networks as the user's IP. By default it sends the device IP captured when the app was installed. If you know the IP of the user's device at the time of the payment, pass it as client_ip_address. Linkrunner forwards it to ad networks (for example Meta client_ip_address) to improve matching.

  • Send only the device's public IP. Private, loopback and link-local addresses are ignored.
  • Leave it out if you don't have it. Linkrunner then uses the install-time device IP.

Responses ​

  1. 200 Payment captured. The response is the same as for a custom event, including processing_id
  2. 400 Missing fields, or all three payment fields were sent but one is invalid
  3. 401 Invalid server key

Website payments ​

If the payment comes from a user of your website rather than your app, send it to POST /capture-payment with "source": "web". The capture-event payment fields apply to app users only. Your website must be tracked with the Web SDK, and the payment then shows up on the Web Events page instead of the app dashboards.

POST: /capture-payment
json
{
  "user_id": "user_12345",
  "payment_id": "ORDER-1001",
  "amount": 499,
  "currency": "INR",
  "type": "FIRST_PAYMENT",
  "status": "PAYMENT_COMPLETED",
  "source": "web"
}
  • Identify the user with user_id. Use the same ID your website passes to lr.identify. install_instance_id does not apply to website users, so user_id is required.
  • Status decides how it counts. A PAYMENT_COMPLETED payment is recorded as a purchase event, the same event the Web SDK sends with lr.track('purchase', …), and counts as a purchase and revenue. Other statuses are recorded as payment_initiated, payment_failed, or payment_cancelled and do not count as revenue.
  • Stored details. amount, currency, payment_id, type, and status are added to the event's event_data, together with any event_data you send. The amount is stored as both amount and value, so a value in your event_data is replaced.
  • Attribution. Linkrunner credits the payment to the channel and campaign of that user's latest visit recorded by the Web SDK in the last 90 days. If the Web SDK has not recorded a visit from that user, the payment shows as Direct.
  • No deduplication. Unlike app payments, every website payment request is stored, including retries with the same type and payment_id. Avoid resending a payment that was already accepted.
  • Send each purchase from one place. If your website also calls lr.track('purchase', …) for the same order, the purchase is counted twice. Track it either in the browser or from your backend, not both.

Meta Ecommerce Events ​

If you are tracking Purchase events to sync with Meta Catalog Sales, you must first map the purchase event with the standard commerce event in the Linkrunner Dashboard before sending it.

Note: Any payment you send should be mapped with Purchase for Commerce Event Manager. For example, map purchase_completed with Purchase.

While you can include any custom attributes in the event_data object, Meta requires specific fields for ecommerce events to correctly attribute catalog sales. Your event_data object should include the following fields:

For comprehensive details on each field requirement, refer to our Meta Commerce Manager documentation.

json
{
  "event_name": "purchase_completed",
  "user_id": "user_12345",
  "payment_id": "ORD-12345",
  "amount": 2000.0,
  "currency": "INR",
  "event_data": {
    "content_ids": ["whshct4mwc"],
    "contents": [
      {
        "id": "whshct4mwc",
        "quantity": 2,
        "item_price": 1000
      }
    ],
    "content_type": "product",
    "currency": "INR",
    "value": 2000.0,
    "num_items": 2,
    "order_id": "order_id_1234"
  }
}

Note: In the example above, map purchase_completed with Purchase in your Linkrunner dashboard before sending it.

To verify your events are being correctly received by Meta, please follow our Testing Ecommerce Events guide.

Need help? Contact support@linkrunner.io.