Skip to main content

Base URL

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

Authentication

All API requests require authentication. Include your server key in the request headers.

Error Responses

  • 401 Unauthorized
    • "Unauthorized access." - Missing or invalid API key
  • 429 Too Many Requests
    • Message: "Rate limit exceeded. Please try again later."
    • Cause: You’ve exceeded the rate limit of 30 requests per second.

Rate Limit Details

  • Rate: 30 requests per second
  • Status code on limit exceeded: 429 (Too Many Requests)

Authentication

All API requests require authentication using an API key. You must include this key in the header of every request.

API Key Header

Include the following header in all API requests:
linkrunner-key: YOUR_API_KEY
Replace YOUR_API_KEY with your actual API key. (Refer instructions below)

Obtaining Your API Key

You can find your API key on the Linkrunner settings page:
  1. Go to https://www.linkrunner.io/settings?s=data-apis
  2. Locate your Server key on this page
  3. Use this key in the linkrunner-key header for all API requests
Keep your API key confidential. Do not share it or expose it in client-side code. Always make API requests from a secure server-side environment.

Endpoints

1. List Campaigns

Retrieve a paginated list of campaigns with optional filtering by status or specific link.

Request

GET /campaigns

Query Parameters

ParameterTypeRequiredDescription
filterstringNoFilter campaigns by status. Options: ACTIVE, INACTIVE, ALL (default: ALL)
linkstringNoFilter campaigns by a specific link URL. The system will extract the campaign from the provided link.
pagenumberNoThe page number to retrieve. Must be a positive integer. (default: 1)
limitnumberNoThe number of campaigns to return per page. Must be between 1 and 1000. (default: 100, max: 1000)

Pagination

Pagination is automatically applied to all requests with the following defaults:
  • Default page: 1
  • Default limit: 100 campaigns per page
  • Maximum limit: 1000 campaigns per page

Example Requests

  1. Basic Request (returns first 100 campaigns):
GET /campaigns
  1. Filter Active Campaigns with Pagination:
GET /campaigns?filter=ACTIVE&page=2&limit=50
  1. Get Campaign by Link:
GET /campaigns?link=https://yourdomain.com?c=XYZ123
  1. All Campaigns with Custom Limit:
GET /campaigns?filter=ALL&limit=200

Response

{
    "msg": "Successfully retrieved 10 campaigns (all campaigns). Showing page 1 of 4.",
    "status": 200,
    "data": {
        "total_campaigns": 10,
        "campaigns": [
            {
                "display_id": "XYZ123",
                "name": "Summer_Promo_2024",
                "created_at": "2024-09-30T09:37:06.989Z",
                "update_at": "2024-09-30T09:37:06.989Z",
                "google": false,
                "meta": true,
                "meta_campaign_id": "987654321098765432",
                "meta_web_to_app": false,
                "active": true,
                "default_link": true,
                "attributed_users": 491,
                "link": "https://yourdomain.com?c=XYZ123",
                "shareable_link": "https://yourdomain.com/XYZ123"
            }
            // ... more campaigns
        ],
        "pagination": {
            "total": 35,
            "pages": 4,
            "page": 1,
            "limit": 10
        }
    }
}

Error Responses

Status CodeError MessageDescription
400”Invalid request parameters.”Invalid link, domain not found, or campaign not found
401”Unauthorized access.”Missing or invalid API key
422”Invalid page number ''. Page must be a positive integer…”Page parameter is not a positive integer
422”Invalid limit ''. Limit must be between 1 and 1000…”Limit parameter is not between 1 and 1000
422”Limit exceeds maximum allowed value of 1000…”Limit exceeds 1000

TypeScript Types

interface Campaign {
    display_id: string;
    name: string;
    created_at: string;
    update_at: string;
    google: boolean;
    meta: boolean;
    meta_campaign_id: string | null;
    meta_web_to_app: boolean;
    active: boolean;
    default_link: boolean;
    attributed_users: number;
    link: string;
    shareable_link: string;
}

interface PaginationInfo {
    total: number;
    pages: number;
    page: number;
    limit: number;
}

interface CampaignsResponse {
    msg: string;
    status: number;
    data: {
        total_campaigns: number;
        campaigns: Campaign[];
        pagination: PaginationInfo;
    };
}

2. Get Attributed Users

Retrieve a paginated list of users attributed to a specific campaign with optional time range filtering.

Request

GET /attributed-users

Query Parameters

ParameterTypeRequiredDescription
display_idstringYesThe display ID of the campaign to retrieve attributed users for
start_timestampstringNoStart time in ISO 8601 format (e.g., “2025-06-23T10:29:26.074”)
end_timestampstringNoEnd time in ISO 8601 format (e.g., “2025-06-23T10:29:26.074”)
timezonestringNoIANA timezone identifier. See IANA Time Zone Database (default: UTC)
pagenumberNoThe page number to retrieve. Must be a positive integer. (default: 1)
limitnumberNoThe number of users to return per page. Must be between 1 and 1000. (default: 50, max: 1000)

Pagination

Pagination is automatically applied to all requests with the following defaults:
  • Default page: 1
  • Default limit: 50 users per page
  • Maximum limit: 1000 users per page

Time Format Details

  • ISO 8601 Format: Use YYYY-MM-DDThh:mm:ss.SSS format (e.g., 2025-06-23T10:29:26.074)
  • IANA Timezone: Standard timezone identifiers like America/New_York, Asia/Tokyo, Asia/Kolkata
  • Default Timezone: UTC is used when timezone parameter is not provided
  • Time Range: Both start and end timestamps are optional; you can filter by start time only, end time only, or both

Example Requests

  1. Basic Request (returns first 50 users):
GET /attributed-users?display_id=XYZ123
  1. With Time Range and Timezone:
GET /attributed-users?display_id=XYZ123&start_timestamp=2025-06-23T10:29:26.074&end_timestamp=2025-06-24T10:29:26.074&timezone=Asia/Kolkata
  1. With Pagination:
GET /attributed-users?display_id=XYZ123&page=2&limit=100
  1. With All Parameters:
GET /attributed-users?display_id=XYZ123&start_timestamp=2025-06-23T10:29:26.074&end_timestamp=2025-06-24T10:29:26.074&timezone=America/New_York&page=3&limit=200

Response

{
    "msg": "Successfully retrieved 123 attributed users for campaign XYZ123. Showing page 1 of 3.",
    "status": 200,
    "data": {
        "total_users": 50,
        "users": [
            {
                "attributed_at": "2024-09-23T08:13:34.417Z",
                "campaign_display_id": "XYZ123",
                "campaign_name": "Summer_Promo_2024",
                "link": null,
                "installed_at": "2024-08-12T20:59:03.000Z",
                "store_click_at": "2024-08-12T20:58:25.000Z",
                "meta_ad_id": "138726495012847390",
                "ad_creative_id": "138726495084763210",
                "ad_creative_name": "Variation_8",
                "ad_set_id": "138726384957162840",
                "ad_set_name": "Engagement",
                "publisher_platform": "instagram",
                "platform_position": null,
                "user_data": {
                    "id": "user123456789",
                    "name": "John Smith",
                    "email": "john.smith@example.com",
                    "phone": "+1234567890",
                    "device_data": {
                        "brand": "Samsung",
                        "base_os": "",
                        "version": "0.7.6",
                        "build_id": "XYZ123.456",
                        "api_level": 33,
                        "bundle_id": "com.example.app",
                        "device_id": "DEVICE123456",
                        "android_id": "ANDROID987654",
                        "device_name": "Galaxy S21",
                        "device_type": "user",
                        "build_number": "2219",
                        "connectivity": "Wi-Fi",
                        "manufacturer": "Samsung",
                        "application_name": "ExampleApp"
                    }
                }
            }
            // ... more users
        ],
        "pagination": {
            "total": 123,
            "pages": 3,
            "page": 1,
            "limit": 50
        }
    }
}

Error Responses

Status CodeError MessageDescription
400”Invalid timezone format.”Invalid IANA timezone identifier provided
400”Invalid timestamp format.”Invalid start or end timestamp format
401”Authentication failed.”Invalid or missing API key
404”Resource not found.”Campaign does not exist in the project
422”Required parameter missing.”Missing required display_id parameter
422”Invalid page number ''. Page must be a positive integer…”Page parameter is not a positive integer
422”Invalid limit ''. Limit must be between 1 and 1000…”Limit parameter is not between 1 and 1000
422”Limit exceeds maximum allowed value of 1000…”Limit exceeds 1000

TypeScript Types

interface DeviceData {
    brand: string;
    base_os: string;
    version: string;
    build_id: string;
    api_level: number;
    bundle_id: string;
    device_id: string;
    android_id: string;
    device_name: string;
    device_type: string;
    build_number: string;
    connectivity: string;
    manufacturer: string;
    application_name: string;
}

interface UserData {
    id: string | null;
    name: string | null;
    email: string | null;
    phone: string | null;
    device_data: DeviceData;
    // Additional user data fields may be included
    [key: string]: any;
}

interface AttributedUser {
    attributed_at: string;
    campaign_display_id: string;
    campaign_name: string;
    link: string | null;
    installed_at: string | null;
    store_click_at: string | null;
    meta_ad_id: string;
    ad_creative_id: string;
    ad_creative_name: string;
    ad_set_id: string;
    ad_set_name: string;
    publisher_platform: string | null;
    platform_position: string | null;
    user_data: UserData;
}

interface PaginationInfo {
    total: number;
    pages: number;
    page: number;
    limit: number;
}

interface AttributedUsersResponse {
    msg: string;
    status: number;
    data: {
        total_users: number;
        users: AttributedUser[];
        pagination: PaginationInfo;
    };
}

Notes

  • All timestamps are in ISO 8601 format.
  • The device_data object contains detailed information about the user’s device.
  • The active field in the campaign data indicates whether the campaign is currently active.
  • The attributed_users field in the campaign data shows the number of users attributed to that campaign.
  • User data provided in this documentation is randomized for privacy reasons. Actual API responses will contain real user data.
  • The TypeScript types provided are based on the example responses
For any help please reach out to darshil@linkrunner.io