> ## Documentation Index
> Fetch the complete documentation index at: https://docs.encorekit.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Creator Links endpoints

> Endpoint contracts for creator affiliate links: mint a creator's permanent tracking links and read their performance stats.

Two endpoints power creator affiliate links: mint the links for a creator, and read that creator's performance. Both authenticate with the publishable key only; no HMAC.

<Note>
  For the scenario (surfacing links in your creator dashboard, link semantics, geo guidance), see the [Creator Links guide](/publishers/offers-api/guides/creator-links).
</Note>

## Authentication

Pass your publishable key in the `X-API-Key` header (`pk_live_*` for production, `pk_test_*` for development). Multi-app projects also send `X-Platform: api`. A test key mints links and returns stats, but clicks against a test-key link are not counted. Full model: [overview's Authentication section](/publishers/offers-api/overview#authentication).

## POST /creators/links

Mints (or fetches) the tracking links for one creator. **Idempotent**: the same `creatorId` always returns the same `linkUrl` per campaign, so it is safe to call on every dashboard load. Links are minted for the campaigns **enabled for your app**, in your **configured campaign order** (both controlled from the dashboard).

```http theme={null}
POST https://api.encorekit.com/encore/publisher/sdk/v1/creators/links
```

### Request

```typescript theme={null}
interface CreateCreatorLinksRequest {
  creatorId: string;   // required: your own opaque creator identifier, 1-128 chars
}
```

| Field       | Type   | Required | Description                                                                                                                                                                                                                                  |
| ----------- | ------ | -------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `creatorId` | string | Yes      | Your own opaque identifier for the creator: any stable id from your system (1 to 128 chars). It's the key everything attributes to; reuse the same value to get the same links back and to read the creator's stats. Never end-user-visible. |

### Response

Each entry carries the same presentation fields as [`POST /offers/catalog`](/publishers/offers-api/reference/catalog) (name, perk, badge, prices, the advertiser `organization`, and the `creatives` set), **plus** a `payout` block, `categories`, and the creator's entry-level `linkUrl`. The one catalog field it drops is the per-creative `clickUrl`: for creator links the tracking link lives once at the entry level.

```typescript theme={null}
interface CreateCreatorLinksResponse {
  creatorId: string;                // echoes the creatorId you sent
  links: Array<{
    campaignId: string;             // campaign this link points to
    linkUrl: string;                // permanent branded short link on link.encorekit.com
    payout: {
      amount: number;               // publisher's share per completion
      currency: string;             // ISO-4217; currently always "USD"
      model: 'CPA' | 'CPC' | 'CPI' | 'CPM';
    };
    name: string;                   // offer name
    perk: string | null;            // value proposition
    badgeLabel: 'free_trial' | 'discount' | null;
    oldPrice: string | null;        // display price before the offer
    newPrice: string | null;        // display price with the offer
    categories: Array<{ id: string; name: string }>;  // filter-tab categories; may be empty
    targetCountries: string[];      // where this campaign converts (ISO 3166-1 alpha-2)
    organization?: {                // the advertiser
      id: string;
      name: string;
      description: string | null;
      url: string | null;
      logoUrl: string | null;
    };
    creatives?: Array<{             // full active set; client picks the primary
      id: string;
      title: string;
      subtitle: string | null;
      description: string | null;
      primaryImageUrl: string | null;
      logoUrl: string | null;
      additionalImages: string[];
      ctaText: string;
      supportedPlatforms: string[]; // 'ios' | 'android' | 'web'
    }>;
  }>;
}
```

| Field                     | Type   | Description                                                                                                                                                                                                                                                      |
| ------------------------- | ------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `links`                   | array  | One entry per campaign enabled for your app, in your configured order. **Empty array** when your app has no eligible campaigns.                                                                                                                                  |
| `links[].campaignId`      | UUID   | The campaign this link points to. Correlate with the [stats endpoint](#get-creatorscreatoridstats), which is keyed by the same `campaignId`.                                                                                                                     |
| `links[].linkUrl`         | URL    | The creator's permanent tracking link on the fixed host `link.encorekit.com` (10-char slug). Stable per `creatorId` per campaign; safe to cache and render on every load. Never expires. Replaces the catalog's per-creative `clickUrl` at the entry level.      |
| `links[].payout`          | object | What you earn on this campaign: `amount` (the publisher's share per completion, same semantics as `earnings` on the stats endpoint), `currency` (currently always `"USD"`), and `model` (`CPA` \| `CPC` \| `CPI` \| `CPM`). Not present in the catalog response. |
| `links[].categories`      | array  | The campaign's categories (`id` + `name`), for filter tabs on your surface. Additive beyond catalog parity; may be empty.                                                                                                                                        |
| `links[].targetCountries` | array  | Where this campaign converts. Surface it so creators can pick offers matching their audience.                                                                                                                                                                    |
| `links[].organization`    | object | The advertiser (catalog parity): `id`, `name`, `description`, `url`, `logoUrl`.                                                                                                                                                                                  |
| `links[].creatives[]`     | array  | The full active creative set for this offer (catalog parity, minus each creative's `clickUrl`). Your client picks which to render as primary; use `supportedPlatforms` to curate per surface.                                                                    |

### Example

```bash theme={null}
# X-Platform is only needed for multi-app projects; single-app keys can omit it.
curl --location --request POST 'https://api.encorekit.com/encore/publisher/sdk/v1/creators/links' \
  --header 'X-API-Key: YOUR_API_KEY' \
  --header 'X-Platform: api' \
  --header 'Content-Type: application/json' \
  --data '{ "creatorId": "creator_abc123" }'
```

```json theme={null}
{
  "creatorId": "creator_abc123",
  "links": [
    {
      "campaignId": "550e8400-e29b-41d4-a716-446655440000",
      "linkUrl": "https://link.encorekit.com/aB3xK9mQ2p",
      "payout": { "amount": 5.00, "currency": "USD", "model": "CPA" },
      "name": "Summer Sale",
      "perk": "3 months of Hulu free",
      "badgeLabel": "free_trial",
      "oldPrice": "$9.99",
      "newPrice": "$0.00",
      "categories": [
        { "id": "d4e5f6a7-0000-4000-8000-000000000001", "name": "Streaming" }
      ],
      "targetCountries": ["US", "GB"],
      "organization": {
        "id": "a1b2c3d4-0000-4000-8000-000000000001",
        "name": "Acme Corp",
        "description": "Streaming, music, and more.",
        "url": "https://acme.com",
        "logoUrl": "https://cdn.encorekit.com/org/acme/logo.png"
      },
      "creatives": [
        {
          "id": "c1d2e3f4-0000-4000-8000-000000000001",
          "title": "Get 3 months of Hulu free",
          "subtitle": "Summer Sale",
          "description": "Limited-time offer for new subscribers.",
          "primaryImageUrl": "https://cdn.encorekit.com/creative/hero.png",
          "logoUrl": "https://cdn.encorekit.com/creative/logo.png",
          "additionalImages": ["https://cdn.encorekit.com/creative/alt.png"],
          "ctaText": "Claim now",
          "supportedPlatforms": ["ios", "android"]
        }
      ]
    }
  ]
}
```

## GET /creators/{creatorId}/stats

Reads a creator's real-time performance: per-campaign aggregates, totals, and a chart-ready daily series.

```http theme={null}
GET https://api.encorekit.com/encore/publisher/sdk/v1/creators/{creatorId}/stats
```

### Path parameters

| Parameter   | Type   | Description                                                              |
| ----------- | ------ | ------------------------------------------------------------------------ |
| `creatorId` | string | The same opaque creator identifier you mint links with (1 to 128 chars). |

### Query parameters

Both date bounds are optional. Omit them for all-time stats, or pass a window to scope everything the endpoint returns: per-campaign aggregates, `totals`, and the `daily` series are all filtered to the range.

| Param       | Type         | Required | Description                       |
| ----------- | ------------ | -------- | --------------------------------- |
| `startDate` | `YYYY-MM-DD` | No       | Inclusive lower bound (UTC date). |
| `endDate`   | `YYYY-MM-DD` | No       | Inclusive upper bound (UTC date). |

A malformed date or a `startDate` later than `endDate` returns a `400`.

### Response

```typescript theme={null}
interface CreatorStatsResponse {
  creatorId: string;      // echoes the creatorId from the path
  startDate?: string;     // echoed only when you supplied one
  endDate?: string;       // echoed only when you supplied one
  currency: string;       // ISO-4217 for EVERY earnings value; currently always "USD"
  campaigns: Array<{
    campaignId: string;   // same id as links[].campaignId from the mint endpoint
    campaignTitle: string;
    clicks: number;       // link opens; each open creates a transaction
    completions: number;  // verified conversions attributed to this creator
    earnings: number;     // your revenue share, in `currency`
  }>;
  totals: {
    clicks: number;
    completions: number;
    earnings: number;
  };
  daily: Array<{          // per-day series across all campaigns, ascending by date
    date: string;         // UTC day, YYYY-MM-DD
    clicks: number;
    completions: number;
    earnings: number;
  }>;
}
```

| Field                     | Type    | Description                                                                                                                                                                                                                                                                                |
| ------------------------- | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `campaigns`               | array   | Per-campaign breakdown, filtered to the date range when provided. Campaigns with zero activity in range are dropped. **Empty array** for a creator with no activity in range, or an unknown `creatorId` (a 200, never a 404), so you can render an empty dashboard without special-casing. |
| `campaigns[].clicks`      | integer | Link opens for this creator on this campaign. Each open creates a transaction, so this counts every click, not unique users.                                                                                                                                                               |
| `campaigns[].completions` | integer | Verified conversions attributed to this creator on this campaign.                                                                                                                                                                                                                          |
| `campaigns[].earnings`    | number  | Your revenue share attributed to this creator on this campaign, in the top-level `currency`.                                                                                                                                                                                               |
| `totals`                  | object  | Sums of `clicks`, `completions`, and `earnings` across all campaigns, within the date range.                                                                                                                                                                                               |
| `daily`                   | array   | Per-day time series aggregated across all campaigns, within the date range. One entry per day **that has activity** (zero-activity days are omitted), ascending by `date`. **Empty array** when there is no activity in range.                                                             |

<Note>
  **Which day a metric lands on.** `clicks` count on the transaction's **created** date. `completions` and `earnings` count on the **completion (verification) date**. So a click on the 1st that completes on the 3rd shows its click on the 1st and its completion plus earnings on the 3rd. All dates are UTC, and this is what the `daily` series and the `startDate`/`endDate` filter operate on.
</Note>

### Example

```bash theme={null}
# startDate / endDate are optional; omit both for all-time stats.
curl --location --request GET \
  'https://api.encorekit.com/encore/publisher/sdk/v1/creators/creator_abc123/stats?startDate=2026-07-01&endDate=2026-07-16' \
  --header 'X-API-Key: YOUR_API_KEY'
```

```json theme={null}
{
  "creatorId": "creator_abc123",
  "startDate": "2026-07-01",
  "endDate": "2026-07-16",
  "currency": "USD",
  "campaigns": [
    {
      "campaignId": "550e8400-e29b-41d4-a716-446655440000",
      "campaignTitle": "Acme Pro - 3 months free",
      "clicks": 1204,
      "completions": 87,
      "earnings": 261.00
    }
  ],
  "totals": { "clicks": 1204, "completions": 87, "earnings": 261.00 },
  "daily": [
    { "date": "2026-07-15", "clicks": 312, "completions": 21, "earnings": 63.00 },
    { "date": "2026-07-16", "clicks": 289, "completions": 19, "earnings": 57.00 }
  ]
}
```

## Status codes

| Code  | Meaning                                                                                                                                                                                                                                    |
| ----- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `200` | Success. On `/creators/links`, `links` may be empty if your app has no eligible campaigns. On `/creators/{creatorId}/stats`, an unknown `creatorId` returns 200 with empty `campaigns`/`daily` and zeroed `totals`, never a 404.           |
| `400` | Malformed request: `creatorId` missing or longer than 128 chars, a malformed `startDate` / `endDate`, or `startDate` later than `endDate`. Also returned when a multi-app key omits the `X-Platform` header. Don't retry; fix the request. |
| `401` | Missing or invalid `X-API-Key`.                                                                                                                                                                                                            |
| `429` | Rate-limited. Back off and retry.                                                                                                                                                                                                          |
| `5xx` | Encore-side failure. Surface a soft error in your dashboard and retry.                                                                                                                                                                     |

## Related

* [Creator Links guide](/publishers/offers-api/guides/creator-links): the dashboard scenario, link semantics, and an end-to-end example.
* [`POST /offers/catalog`](/publishers/offers-api/reference/catalog): the catalog projection these display fields mirror.
* [API Reference overview](/publishers/offers-api/overview): auth and the claim model.
