linkrunway.
Implementation guide

Build the connection once.

Use the API and SDKs to connect links, identity, and outcomes.

Get started
A developer concentrating on his laptop in a daylight workspace
The essentials

Client SDKs resolve links and collect consented activity. Your authenticated backend supplies canonical customer IDs and financial events to POST /v1/track using a server key.

Before you begin.

  • Workspace-specific publishable and server keys
  • An authenticated backend with a stable customer ID
  • A consent flow appropriate to your app

Keep the trust boundary clear.

Use lr_pk keys for client collection and lr_sk keys on your server. Publishable events cannot establish canonical customer identity or create purchases, subscriptions, or refunds.

  • Create separate keys for each workspace.
  • Store server keys outside browser code and app bundles.
  • Rotate a leaked key in Settings before shipping a replacement.

Capture a consented connection.

The JavaScript SDK is included in packages/sdk. Import it as a workspace dependency. Initialize it after consent and preserve the signed token for the authenticated signup flow.

JavaScript · client
import { LinkRunway } from '@linkrunway/sdk';

const runway = new LinkRunway({
  endpoint: 'https://links.example.com',
  apiKey: 'lr_pk_your_publishable_key',
  consent: true,
});
runway.capture(window.location.href);
await runway.track({
  eventId: crypto.randomUUID(),
  type: 'OPEN',
});

Verify the outcome on your server.

Send your server-verified customer ID and the saved click token to POST /v1/track. Use the provider’s unique payment identifier as the event ID. Stripe users can use the signed revenue connector instead of a separate manual payment event.

JSON · POST /v1/track with a server Bearer key
{
  "eventId": "payment_unique_123",
  "type": "PURCHASE",
  "externalUserId": "customer_123",
  "clickToken": "SIGNED_CLICK_TOKEN",
  "amount": 2900,
  "currency": "USD",
  "consent": true
}

Make retries boring.

Persist the event ID before sending it. Retry transient failures with the same payload and ID. Keep event timestamps within the supported 90-day ingestion window, and use a new ID for each partial refund.

JSON · partial refund
{
  "eventId": "refund_unique_456",
  "type": "REFUND",
  "originalEventId": "payment_unique_123",
  "amount": 1000,
  "currency": "USD",
  "consent": true
}

Find the missing connection.

403 for a financial event

Use a server key. Verify payments on your backend before reporting them.

409 for an existing event ID

The ID was reused with conflicting financial fields, or a refund exceeded the balance. Reconcile the business event instead of inventing a retry ID.

Click token expired

Do not fabricate a replacement token. Preserve the verified outcome and investigate attribution separately.

Reviewed October 10, 2026 · LinkRunway documentation

A little clarity

Good questions.
Clear answers.

Which key belongs in a mobile app?

A publishable key. Never ship a server key in JavaScript served to the browser, an iOS bundle, or an Android package.

What unit should the payment amount use?

Use integer minor currency units: 2900 for USD 29.00, 2900 for JPY 2900, and 29000 for KWD 29.000. Include the uppercase ISO currency code.

What should I retry?

Retry transient failures with the same event ID and payload. Resolve validation and authorization errors before retrying. A conflicting reuse of an event ID returns a conflict.

See the platform
Your next chapter

Let’s see where
a little link takes you.

Start for free Explore pricing