Skip to content

Developers

Linkchime API reference

Create short links, import them in bulk, and read campaign analytics with a workspace API key. Same API the app uses — scoped to one workspace.

Overview

The Linkchime API is a JSON REST API at /api/v1. Create an API key in Workspace settings → Developer API, then send it on every request. Keys are bound to one workspace — you do not pass a workspace header.

Landing pages, conversion goals, scheduled reports, and workspace settings are available on the same API. API keys cannot manage other keys, workspaces, billing, or the AI assistant.

Base URL

https://api.linkchime.com

Browser extension

The Chrome extension shortens the current tab or a right-clicked URL with a workspace API key and copies the short link. Load it unpacked from the extension/ folder in the project, then set your key under Options. It defaults to api.linkchime.com; change the API base for a self-hosted instance. A Chrome Web Store listing will be linked here once published.

Authentication

Send the secret as a Bearer token or as X-Api-Key. Production keys start with lc_live_. The secret is shown once when you create the key.

Request headers

Authorizationrequired

Bearer lc_live_…

API key as a Bearer token.

X-Api-Key

lc_live_…

Alternative to Authorization. Same secret.

Content-Type

application/json

Required on POST and PATCH bodies.

Create your first link

Once you have a key, this is the smallest request that creates a branded short link.

curl -X POST 'https://api.linkchime.com/api/v1/links' \
  -H 'Authorization: Bearer YOUR_API_KEY' \
  -H 'Content-Type: application/json' \
  -d '{"destination_url":"https://example.com/summer-sale","slug":"summer","title":"Summer sale","metadata":{"utm":{"source":"newsletter","medium":"email","campaign":"summer-sale"}}}'

Errors

Failed requests return JSON with an error object. Rate-limited responses also include a Retry-After header (seconds). When Turnstile is enabled, sign-in and registration require CF-Turnstile-Response; 403s use code turnstile_required. Public abuse reports use the same challenge header when Turnstile is on. Blocked destinations return 422 destination_blocked. Suspended accounts return 403 account_suspended. Session 429s may include details.challenge: "turnstile"; send CF-Turnstile-Response after solving to continue. API keys are not challenged.

400 · validation_error

json

{
  "error": {
    "code": "validation_error",
    "message": "destination_url is required"
  }
}

401 · unauthorized

json

{
  "error": {
    "code": "unauthorized",
    "message": "invalid api key"
  }
}

403 · forbidden

json

{
  "error": {
    "code": "forbidden",
    "message": "api access is not available on your plan"
  }
}

404 · not_found

json

{
  "error": {
    "code": "not_found",
    "message": "link not found"
  }
}

409 · conflict

json

{
  "error": {
    "code": "conflict",
    "message": "slug already exists"
  }
}

429 · rate_limited

json

{
  "error": {
    "code": "rate_limited",
    "message": "too many api requests",
    "details": {
      "challenge": "turnstile",
      "site_key": "0x4AAAAAAA..."
    }
  }
}

Pagination

List endpoints return a next_cursor when more rows exist. Pass it as cursor on the next request. Default page size is 20 for links and import jobs.

Plan limits

Rate limits and import size follow the workspace plan. Defaults for hosted Free and Pro:

LimitFreePro
API rate limit5 req/s50 req/s
Links per import job10010,000
Concurrent import jobs15
API keys225

Links

Bulk import

POST/api/v1/import-jobs

Create an import job

Starts an async bulk create. Poll the job, then fetch per-row short URLs.

Requires API key · 202

Request body

linksrequired

CreateLinkRequest[]

One or more link payloads. Max size is your plan’s max_import_job_size.

  • Returns immediately. Poll GET /api/v1/import-jobs/{jobId} until status is completed, failed, or cancelled.
  • Requires the api_access plan feature.

Request

curl -X POST 'https://api.linkchime.com/api/v1/import-jobs' \
  -H 'Authorization: Bearer YOUR_API_KEY' \
  -H 'Content-Type: application/json' \
  -d '{"links":[{"destination_url":"https://example.com/a","metadata":{"utm":{"campaign":"summer-sale"}}},{"destination_url":"https://example.com/b"}]}'

Response

json

{
  "data": {
    "id": "c2a91f07-6d44-4b18-9e3a-7f1c0b5d2e88",
    "workspace_id": "e7d2b4a1-9c80-4f3e-b6a2-0d15c8e4a973",
    "status": "pending",
    "total_count": 2,
    "succeeded_count": 0,
    "failed_count": 0,
    "skipped_count": 0,
    "created_at": "2026-08-12T16:05:00Z"
  }
}
GET/api/v1/import-jobs

List import jobs

Returns recent import jobs for the workspace.

Requires API key · 200

Query parameters

limit

integer

Page size. Default 20.

cursor

string

Opaque cursor from next_cursor.

Request

curl -X GET 'https://api.linkchime.com/api/v1/import-jobs' \
  -H 'Authorization: Bearer YOUR_API_KEY'

Response

json

{
  "data": {
    "jobs": [
      {
        "id": "c2a91f07-6d44-4b18-9e3a-7f1c0b5d2e88",
        "status": "completed",
        "total_count": 2,
        "succeeded_count": 2,
        "failed_count": 0,
        "skipped_count": 0,
        "created_at": "2026-08-12T16:05:00Z",
        "completed_at": "2026-08-12T16:05:02Z"
      }
    ]
  }
}
GET/api/v1/import-jobs/{jobId}

Get import job

Returns status and progress counts. Poll until completed, failed, or cancelled.

Requires API key · 200

Path parameters

jobIdrequired

uuid

Import job ID.

Request

curl -X GET 'https://api.linkchime.com/api/v1/import-jobs/c2a91f07-6d44-4b18-9e3a-7f1c0b5d2e88' \
  -H 'Authorization: Bearer YOUR_API_KEY'

Response

json

{
  "data": {
    "id": "c2a91f07-6d44-4b18-9e3a-7f1c0b5d2e88",
    "workspace_id": "e7d2b4a1-9c80-4f3e-b6a2-0d15c8e4a973",
    "status": "completed",
    "total_count": 2,
    "succeeded_count": 2,
    "failed_count": 0,
    "skipped_count": 0,
    "created_at": "2026-08-12T16:05:00Z",
    "started_at": "2026-08-12T16:05:00Z",
    "completed_at": "2026-08-12T16:05:02Z"
  }
}
DELETE/api/v1/import-jobs/{jobId}

Cancel import job

Cancels a pending import job.

Requires API key · 200

Path parameters

jobIdrequired

uuid

Import job ID.

  • Only pending jobs can be cancelled.

Request

curl -X DELETE 'https://api.linkchime.com/api/v1/import-jobs/c2a91f07-6d44-4b18-9e3a-7f1c0b5d2e88' \
  -H 'Authorization: Bearer YOUR_API_KEY'

Response

json

{
  "data": {
    "id": "c2a91f07-6d44-4b18-9e3a-7f1c0b5d2e88",
    "status": "cancelled",
    "total_count": 2,
    "succeeded_count": 0,
    "failed_count": 0,
    "skipped_count": 2
  }
}
GET/api/v1/import-jobs/{jobId}/results

Get import results

Per-row results, including short_url for succeeded rows.

Requires API key · 200

Path parameters

jobIdrequired

uuid

Import job ID.

Query parameters

limit

integer

Page size. Default 50.

cursor

string

Opaque cursor from next_cursor.

  • short_url is present on succeeded rows after the job completes.

Request

curl -X GET 'https://api.linkchime.com/api/v1/import-jobs/c2a91f07-6d44-4b18-9e3a-7f1c0b5d2e88/results' \
  -H 'Authorization: Bearer YOUR_API_KEY'

Response

json

{
  "data": {
    "items": [
      {
        "row_index": 0,
        "status": "succeeded",
        "link_id": "8f3c1a2e-4b7d-4e91-9c2a-1d6b8e0f4a21",
        "short_url": "https://go.example.com/summer"
      }
    ]
  }
}

Domains

GET/api/v1/domains

List domains

Lists custom domains in the workspace, including DNS instructions.

Requires API key · 200

Request

curl -X GET 'https://api.linkchime.com/api/v1/domains' \
  -H 'Authorization: Bearer YOUR_API_KEY'

Response

json

{
  "data": {
    "items": [
      {
        "id": "b14e9c70-2a55-4f08-8d31-9c6a4e2b1f05",
        "workspace_id": "e7d2b4a1-9c80-4f3e-b6a2-0d15c8e4a973",
        "hostname": "go.example.com",
        "status": "verified",
        "verification_token": "lc_verify_9f2a",
        "dns": {
          "txt_record_name": "_go.example.com",
          "txt_record_value": "linkchime-verify=lc_verify_9f2a",
          "cname_target": "cname.linkchime.com"
        }
      }
    ]
  }
}
GET/api/v1/domains/{domainId}

Get a domain

Returns a custom domain by ID.

Requires API key · 200

Path parameters

domainIdrequired

uuid

Domain ID.

Request

curl -X GET 'https://api.linkchime.com/api/v1/domains/b14e9c70-2a55-4f08-8d31-9c6a4e2b1f05' \
  -H 'Authorization: Bearer YOUR_API_KEY'

Response

json

{
  "data": {
    "id": "b14e9c70-2a55-4f08-8d31-9c6a4e2b1f05",
    "hostname": "go.example.com",
    "status": "verified",
    "workspace_id": "e7d2b4a1-9c80-4f3e-b6a2-0d15c8e4a973"
  }
}

Analytics

GET/api/v1/analytics

Workspace analytics

Aggregated clicks, audience, and campaign breakdowns for the workspace.

Requires API key · 200

Query parameters

from

date

Inclusive start date (YYYY-MM-DD).

to

date

Inclusive end date (YYYY-MM-DD).

granularity

day | hour

Bucket size for clicks_by_period.

top

integer

How many breakdown rows to return.

Request

curl -X GET 'https://api.linkchime.com/api/v1/analytics' \
  -H 'Authorization: Bearer YOUR_API_KEY'

Response

json

{
  "data": {
    "total_clicks": 12840,
    "clicks_in_period": 932,
    "previous_clicks_in_period": 801,
    "unique_visitors": 744,
    "clicks_by_period": [
      {
        "period": "2026-08-11",
        "clicks": 410
      }
    ],
    "channels": [
      {
        "label": "email",
        "clicks": 220
      }
    ],
    "countries": [
      {
        "label": "US",
        "clicks": 510
      }
    ]
  }
}
GET/api/v1/links/{linkId}/analytics

Link analytics

Analytics report for a single link.

Requires API key · 200

Path parameters

linkIdrequired

uuid

Link ID.

Query parameters

from

date

Inclusive start date (YYYY-MM-DD).

to

date

Inclusive end date (YYYY-MM-DD).

granularity

day | hour

Bucket size for clicks_by_period.

Request

curl -X GET 'https://api.linkchime.com/api/v1/links/8f3c1a2e-4b7d-4e91-9c2a-1d6b8e0f4a21/analytics' \
  -H 'Authorization: Bearer YOUR_API_KEY'

Response

json

{
  "data": {
    "total_clicks": 412,
    "clicks_in_period": 88,
    "unique_visitors": 71,
    "clicks_by_period": [
      {
        "period": "2026-08-11",
        "clicks": 40
      }
    ]
  }
}
GET/api/v1/analytics/export

Export clicks

Downloads workspace click events as CSV.

Requires API key · 200

Query parameters

from

date

Inclusive start date.

to

date

Inclusive end date.

  • Returns text/csv. Requires analytics_export on your plan.

Request

curl -X GET 'https://api.linkchime.com/api/v1/analytics/export' \
  -H 'Authorization: Bearer YOUR_API_KEY'

Response

csv

clicked_at,slug,country,device,channel
2026-08-11T09:14:02Z,summer,US,mobile,email

Campaigns

GET/api/v1/campaigns

List campaigns

Lists UTM campaigns with link and click counts.

Requires API key · 200

  • Campaigns are grouped from metadata.utm.campaign on your links.

Request

curl -X GET 'https://api.linkchime.com/api/v1/campaigns' \
  -H 'Authorization: Bearer YOUR_API_KEY'

Response

json

{
  "data": {
    "items": [
      {
        "name": "summer-sale",
        "link_count": 12,
        "total_clicks": 1840
      }
    ]
  }
}
GET/api/v1/campaigns/{campaign}/analytics

Campaign analytics

Aggregated analytics for every link tagged with that campaign.

Requires API key · 200

Path parameters

campaignrequired

string

UTM campaign name.

Query parameters

from

date

Inclusive start date.

to

date

Inclusive end date.

granularity

day | hour

Bucket size for clicks_by_period.

Request

curl -X GET 'https://api.linkchime.com/api/v1/campaigns/summer-sale/analytics' \
  -H 'Authorization: Bearer YOUR_API_KEY'

Response

json

{
  "data": {
    "total_clicks": 1840,
    "clicks_in_period": 220,
    "unique_visitors": 190
  }
}

Account

GET/api/v1/me

Current actor

Returns the actor, bound workspace, plan, and entitlements for this API key.

Requires API key · 200

  • API keys are bound to one workspace. workspaces contains only that workspace.

Request

curl -X GET 'https://api.linkchime.com/api/v1/me' \
  -H 'Authorization: Bearer YOUR_API_KEY'

Response

json

{
  "data": {
    "actor": {
      "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
      "email": "you@example.com"
    },
    "workspace": {
      "id": "e7d2b4a1-9c80-4f3e-b6a2-0d15c8e4a973",
      "name": "Acme"
    },
    "workspaces": [
      {
        "id": "e7d2b4a1-9c80-4f3e-b6a2-0d15c8e4a973",
        "name": "Acme"
      }
    ],
    "workspace_access": {
      "is_owner": true
    },
    "entitlements": {
      "api_access": true,
      "api_rate_limit_rps": 5
    }
  }
}

Tracking

GET/c/{slug}/pixel.gif

Conversion pixel

Records a conversion for a goal on a short link. Public GIF endpoint.

No authentication · 200

Path parameters

slugrequired

string

Link slug.

Query parameters

goalrequired

string

Conversion goal slug.

  • Public tracking pixel. Embed on a thank-you page. No API key required.

Request

curl -X GET 'https://api.linkchime.com/c/summer/pixel.gif'

Response

csv

(1×1 GIF)

Is there a browser extension?

Yes. Load the Manifest V3 extension unpacked from the extension/ folder, or install it from the Chrome Web Store when published. It uses a workspace API key and defaults to Linkchime Cloud; self-hosted APIs are set in Options.

Where do I create an API key?

Sign in, open Workspace settings, and use the Developer API card. You must be the workspace owner, and API access must be on your plan. The secret is shown only once.

Do I need a workspace header?

No. Each key is scoped to one workspace. Session tokens can send X-Workspace-Id; API keys ignore that and always use the bound workspace.

What can API keys not do?

They cannot create or revoke other keys, manage workspaces or members, access billing, or use the AI assistant. Everything else in this reference works with a key.

Your next campaign should look like you.

Make a branded short link, QR, or page in a few minutes. Free plan, no card. Analytics are there when you need to explain what worked.