Shark TrackAPI
Open dashboard

Shark Track API

Create and manage short links, variants, projects and analytics over plain HTTP. Everything the dashboard does, the API does.

Quickstart

Create a key in the dashboard under Settings › API keys. It is shown once. Store it in an environment variable rather than pasting it into a file or a chat.

# Create a link. The utm_source is lifted out of the URL automatically.
curl -sX POST https://app.shrk.in/v1/links \
  -H "Authorization: Bearer $SHARK_TRACK_KEY" \
  -H "content-type: application/json" \
  -d '{"destination":"https://example.com/sale?utm_source=newsletter"}'
{
  "id": "lnk_8Kq2mXpR",
  "shortUrl": "https://shrk.in/aB3xY9",
  "destination": "https://example.com/sale",
  "params": { "utm_source": "newsletter" }
}

Authentication

Send the key as a bearer token on every request. The base URL is https://app.shrk.in/v1.

Authorization: Bearer stk_live_...
ScopeWhat it allows
readEvery GET. Links, analytics, exports, QR codes. Cannot change anything.
writeEverything read allows, plus create, update and delete.

Keys cannot manage other keys, and cannot sign in. A key inherits the powers of the account that created it, so only a superuser key can set or rename a custom slug.

Concepts worth knowing

Tracking parameters are invisible in the link. You set them on the link; the redirect applies them to the destination and records them against the click. The URL you share is always the bare https://shrk.in/<slug>.

UTMs are lifted from URLs you submit. Post a destination carrying utm_source and it becomes a tracking parameter. Functional parameters like id=482 stay on the destination, because the page needs them.

A variant is a second address to the same destination, like shrk.in/sale/email, with its own parameters layered over the link's. A project is a folder; a link belongs to at most one, while tags are many per link.

All timestamps are epoch milliseconds. clickCount counts humans; bot hits are counted separately in botCount and excluded from analytics unless you pass bots=1.

Errors

Every failure returns the same shape. Branch on code, never on the message, which may be reworded.

{
  "error": {
    "code": "delete_requires_dashboard",
    "message": "This link has 143 recorded clicks. Sign in to delete it, or archive it instead.",
    "field": null
  }
}
CodeMeaning
key_missingNo Authorization header
key_unknownNot a valid key
key_revokedRevoked in the dashboard
key_expiredPast its expiry
insufficient_scopeA read key attempted a change
invalid_requestBad input; field says which
conflictSlug or name already taken
delete_requires_dashboardThe link has recorded clicks
rate_limitedToo many requests

Rate limits

600 requests per minute per key. Every response carries X-RateLimit-Limit and X-RateLimit-Remaining, and a 429 carries Retry-After in seconds.

Endpoints

MethodPathWhat it does
GET /links List links
POST /links Create a linkAny utm_ keys on the destination are lifted into params automatically. Other query parameters stay on the destination. A custom slug requires a superuser key; leave it out for a generated one.
POST /links/bulk/create Create many linksOne URL per line, up to 200. A tab after a URL makes the rest its title. utm_ keys are lifted from each line. Exact repeats are skipped.
POST /links/bulk/params Apply parameters to many links
POST /links/bulk/preview Preview a bulk pasteParses without creating. Use this to check what a paste will do.
POST /links/bulk/project Move many links into a project
GET /links/tags List tags in use
GET /links/{id} Get a link
PATCH /links/{id} Update a linkSend only the fields you want to change. Setting status to archived hides a link while keeping it working.
DELETE /links/{id} Delete a linkOnly links with no recorded human clicks can be deleted through the API. A link with clicks returns 409 with code `delete_requires_dashboard`; archive it instead, or delete it from the dashboard. Bot-only links are deletable.
GET /links/{id}/clicks Recent clicks
GET /links/{id}/export.csv Export clicks as CSV
GET /links/{id}/qr.svg QR code
GET /links/{id}/stats Analytics for a linkTotals, a time series, and breakdowns by country, city, device, OS, browser, referrer, traffic type, UTM source, medium and campaign, custom parameters, variant and language. Also lists variant codes that were clicked but match no variant.
GET /links/{id}/variants List variants
POST /links/{id}/variants Create a variantA variant is a second address to the same destination: shrk.in/<slug>/<code>. Its params layer over the link's.
PATCH /links/{id}/variants/{variantId} Update a variant
DELETE /links/{id}/variants/{variantId} Delete a variantPast clicks are kept and report as an unrecognised code afterwards.
GET /me Who this key belongs to
GET /projects List projects
POST /projects Create a project
PATCH /projects/{id} Rename a project
DELETE /projects/{id} Delete a projectLinks inside are unfiled, never deleted.
GET /workspace Workspace details
GET /workspace/stats Analytics across every link

Paths are relative to https://app.shrk.in/v1. The OpenAPI 3.1 spec has full request and response schemas.

Deleting links

A link with recorded clicks cannot be deleted through the API. Losing analytics history to an automated call is not recoverable, so it returns 409 with code delete_requires_dashboard. Links with no human clicks delete normally, and bot-only links count as empty.

Archive instead. The link keeps working and keeps its history, it just leaves the list.

curl -sX PATCH https://app.shrk.in/v1/links/lnk_123 \
  -H "Authorization: Bearer $SHARK_TRACK_KEY" \
  -H "content-type: application/json" \
  -d '{"status":"archived"}'

Use with Claude

No MCP server needed. Claude can call this API directly with curl, and read the spec to work out how.

1. Put the key in the environment

export SHARK_TRACK_KEY="stk_live_..."

Never paste the key into a chat message or commit it. Claude reads it from the environment when it runs a command.

2. Point Claude at the spec

The Shark Track API is documented at https://docs.shrk.in/llms.txt
and the full spec is at https://docs.shrk.in/openapi.json
My key is in $SHARK_TRACK_KEY. Create short links for these five URLs
and put them in a project called Q4 launch.

llms.txt is the compact version and fits comfortably in context. Use the OpenAPI spec when exact schemas matter.

3. Give it a read key unless it needs to write

An agent holding a write key can be steered by content it reads. If Claude browses a page or opens a document containing instructions, a prompt injection could create or change links on your account. Use a read-only key for reporting work, and a write key only when you are asking for changes. Revoke from the dashboard the moment a key is no longer needed.

Useful things to ask for: a weekly summary of which links got clicks and from where, a variant per channel across a set of links, a CSV export pulled into a spreadsheet, or a batch of links built from a list of URLs.