Events and revenue
POST /v1/track accepts consented events. Publishable keys produce unverified client events. Server keys produce verified events and are required for PURCHASE, SUBSCRIPTION, and REFUND.
Event fields
| Field | Requirement |
|---|---|
eventId | Required stable string, 1–150 characters |
type | INSTALL, OPEN, SIGNUP, PURCHASE, SUBSCRIPTION, REFUND, or CUSTOM |
consent | Required literal true |
name | Optional event name, at most 120 characters |
clickToken | Optional signed attribution token, at most 1,500 characters |
externalUserId | Optional stable customer ID, 1–200 characters; canonical identity requires a server key |
amount | Integer minor units, 0–1,000,000,000; default 0; non-financial events must use 0 |
currency | Three uppercase letters; default USD |
originalEventId | Required for refunds and forbidden for other types |
metadata | Flat metadata object; see API conventions |
occurredAt | Optional ISO timestamp; defaults to receipt time |
installId | Optional UUID; SDKs manage installation identity |
attestation | Optional device attestation token, at most 2,000 characters |
Timestamps must be within the previous 90 days and no more than 60 seconds in the future. Synchronize backend clocks. A provided invalid or expired click token fails validation; do not manufacture tokens.
Send trusted revenue
Verify payment with your payment provider in your backend first. Derive amount, currency, customer ID, and event ID from that verified payment record. Persist the delivery in a durable outbox before calling LinkRunway.
# Example only: send after verifying the payment in your backend.
curl --fail-with-body https://api.linkrunway.com/v1/track \
-H "Authorization: Bearer $LINKRUNWAY_SERVER_KEY" \
-H 'Content-Type: application/json' \
--data '{"eventId":"payment_example_001","type":"PURCHASE","externalUserId":"customer_example_001","amount":1999,"currency":"USD","consent":true}'1999 represents USD 19.99. Supply a genuine clickToken when your consented journey has one, or let the configured customer attribution policy evaluate eligible prior touches. A successful event can be unattributed. Revenue ingestion does not promise a commission: attribution, partner status, fraud checks, and event type also matter.
Idempotency
A successful response is { id, attributed, duplicate }. Retrying an accepted event ID returns the original record with duplicate: true. Changing its type, amount, currency, or refund reference returns 409. Other retry fields do not rewrite an already-recorded event. Keep the complete original payload stable.
Client events are stored under the reserved app: namespace; server events must not use IDs beginning with app:. A client cannot reserve a future server payment ID. Deduplication is workspace-scoped, so never rely on the same ID to deduplicate across workspaces.
For invoice renewals, use the provider's unique paid invoice ID. For refunds, use a unique refund ID. Never create a fresh random event ID merely because a network request timed out.
Refunds
{
"eventId": "refund_example_001",
"type": "REFUND",
"originalEventId": "payment_example_001",
"amount": 500,
"currency": "USD",
"consent": true
}Send the original caller-supplied event ID, not LinkRunway's internal id. Refunds must refer to an eligible original revenue event in the same workspace and use its currency. Use positive minor units; the service records the reversal. Partial refunds must not exceed the remaining original amount. A retry must retain its refund ID and amount.
Delivery and attribution
Use event webhooks to consume recorded events. Treat verified and attribution as separate facts. A client SIGNUP is telemetry; a server-authenticated SIGNUP can identify the customer. A webhook is not a second payment authorization.
Use errors and retries for delivery recovery and testing for a complete verification sequence.