Appearance
Revenue tracking API
Documentation for Linkrunner Revenue Tracking API
Deprecated for app paymentsPOST /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/v1Authentication
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-KEYCapture 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-eventRequest Body
json
{
"event_name": "purchase_completed",
"amount": 250.96,
"payment_id": "ORD-12345",
"currency": "USD",
"user_id": "user_12345"
}| Parameter | Type | Description |
|---|---|---|
| event_name | string | Required. Name of the payment, stored as the payment type |
| amount | number | Required for a payment. Zero or more. A numeric string is also accepted |
| payment_id | string | Required for a payment. Your unique transaction ID |
| currency | string | Required for a payment. 3-letter ISO 4217 code, for example USD or INR |
| status | string | Optional. Defaults to PAYMENT_COMPLETED |
| user_id | string | Required 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_id | string | Required unless user_id is sent. Linkrunner's ID for the install |
| event_data | object | Optional. Additional data, such as ecommerce fields |
| client_ip_address | string | Optional. 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
- 200 Payment captured. The response is the same as for a custom event, including
processing_id - 400 Missing fields, or all three payment fields were sent but one is invalid
- 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-paymentjson
{
"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 tolr.identify.install_instance_iddoes not apply to website users, souser_idis required. - Status decides how it counts. A
PAYMENT_COMPLETEDpayment is recorded as apurchaseevent, the same event the Web SDK sends withlr.track('purchase', …), and counts as a purchase and revenue. Other statuses are recorded aspayment_initiated,payment_failed, orpayment_cancelledand do not count as revenue. - Stored details.
amount,currency,payment_id,type, andstatusare added to the event'sevent_data, together with anyevent_datayou send. The amount is stored as bothamountandvalue, so avaluein yourevent_datais 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
typeandpayment_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.