SHORTCLIX REST API – User Guide
The SHORTCLIX REST API lets you manage your projects and short links, generate QR codes, and read click analytics straight from your own scripts, automations (Zapier, Make, n8n …) or AI tools.
Availability: The API is part of the Basic and Pro plans. It is not available on the Free plan. Every token belongs to one workspace, and all plan limits of that workspace apply to the API exactly as they do in the dashboard.
- Base URL:
https://shortclix.com/api/v1 - Format: JSON. Always send
Accept: application/json. - Auth: Bearer token (see Authentication).
Table of contents
- Authentication
- Request & response basics
- Rate limits
- Errors
- Projects
- Short links
- QR codes
- Analytics
- Full example: track a link end-to-end
- Field reference
Authentication
1. Create a token
- Open your dashboard and switch to the workspace you want the token to control.
- Go to Workspace Settings. (Only workspace owners can manage tokens.)
- In the API Tokens section, enter a name (e.g.
Zapier,MCP client), choose the permissions, and click Create token. - Copy the token immediately – it is shown only once. If you lose it, revoke it and create a new one.
The API Tokens section only appears when your plan includes API access.
Token format: A token looks like
2|KwCUgJwAg3UqqaBVlpO…. The leading2|(a number followed by a pipe) is a normal part of the token — copy and send the whole string. Tokens cannot be retrieved again after creation; if you lose one, revoke it and create a new one.
Permissions (scopes)
| Scope | Allows |
|---|---|
| Read only | All GET endpoints (list/show/analytics/QR) |
| Read & write | Everything above plus creating, updating and deleting projects and links |
Choose the least privilege you need. A read-only token cannot modify anything.
2. Send the token
Pass the token as a Bearer token on every request:
curl https://shortclix.com/api/v1/projects \
-H "Authorization: Bearer YOUR_TOKEN_HERE" \
-H "Accept: application/json"
A token is tied to the workspace it was created in. It can never see or change data in another workspace, even if you belong to several.
3. Revoke a token
In Workspace Settings → API Tokens, click Revoke next to any token. Applications using it lose access immediately.
Request & response basics
-
Send request bodies as JSON (
Content-Type: application/json) forPOST/PATCH. -
Single resources are wrapped in a
dataobject; collections in adataarray:{ "data": { "id": 1, "name": "Launch Campaign" } } -
IDs: Projects can be addressed by their numeric
idor theirslug. Short links are addressed by theirshort_code(see Identifying a link). -
Timestamps are returned in ISO-8601 (
2026-06-07T14:30:00+00:00). -
Listing endpoints return all matching records (no pagination).
Rate limits
Each token is limited to 60 requests per minute. Exceeding it returns HTTP 429. Standard
X-RateLimit-Limit / X-RateLimit-Remaining headers are included on every response.
Errors
The API uses conventional HTTP status codes and a JSON body with a message.
| Status | Meaning |
|---|---|
| 200 / 201 / 204 | Success (204 = deleted, no body) |
| 401 Unauthorized | Missing or invalid token |
| 403 Forbidden | Plan has no API access, token is read-only on a write call, or the token's workspace is unavailable |
| 404 Not Found | Resource does not exist in this workspace |
| 409 Conflict | Ambiguous lookup (a destination URL matched more than one link) |
| 422 Unprocessable Entity | Validation failed, or a plan limit was reached |
| 429 Too Many Requests | Rate limit exceeded |
Validation error example:
{
"message": "The original url field is required.",
"errors": { "original_url": ["The original url field is required."] }
}
Plan-limit error example (you reached the maximum number of projects/links for your plan):
{
"message": "Your plan does not allow creating more short links.",
"plan_limit_reached": true
}
Projects
A project groups your short links.
List projects
GET /api/v1/projects
{
"data": [
{
"id": 1,
"name": "Launch Campaign",
"slug": "launch-campaign",
"description": null,
"monthly_report_recipients": null,
"weekly_report_recipients": null,
"short_links_count": 4,
"created_at": "2026-06-01T09:00:00+00:00",
"updated_at": "2026-06-01T09:00:00+00:00"
}
]
}
Create a project
POST /api/v1/projects
| Field | Required | Notes |
|---|---|---|
name |
yes | Max 255 chars |
slug |
no | Auto-generated from name if omitted. Globally unique, max 255 |
description |
no | Max 1000 chars |
monthly_report_recipients |
no | Comma-separated email list |
weekly_report_recipients |
no | Comma-separated email list |
curl -X POST https://shortclix.com/api/v1/projects \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Accept: application/json" \
-H "Content-Type: application/json" \
-d '{"name": "Launch Campaign"}'
Returns 201 with the created project. Returns 422 with plan_limit_reached if you are at your
plan's project limit.
Show / update / delete
GET /api/v1/projects/{id-or-slug}
PATCH /api/v1/projects/{id-or-slug}
DELETE /api/v1/projects/{id-or-slug}
PATCH accepts any subset of the create fields. DELETE returns 204 and removes the project and
all its short links.
Short links
List links
GET /api/v1/links # all links in the workspace
GET /api/v1/projects/{id-or-slug}/links # links of one project
{
"data": [
{
"id": 10,
"project_id": 1,
"short_code": "launch",
"short_url": "https://shortclix.com/launch",
"original_url": "https://example.com/my-long-link",
"title": "Launch link",
"is_active": true,
"is_effectively_active": true,
"redirect_url": null,
"expires_at": null,
"created_at": "2026-06-02T12:00:00+00:00",
"updated_at": "2026-06-02T12:00:00+00:00"
}
]
}
is_effectively_activeisfalsewhen the link is disabled or itsexpires_athas passed.
Create a link
POST /api/v1/projects/{id-or-slug}/links
| Field | Required | Notes |
|---|---|---|
original_url |
yes | The destination. Supports https://, http://, mailto:, tel:. Max 2048 |
title |
yes | Label for your own reference. Max 255 |
short_code |
no | Auto-generated (6 chars) if omitted. Otherwise normalized (lowercase, dashes), must be unique and not a reserved word |
expires_at |
no | ISO-8601 date/time; link stops working afterwards |
is_active |
no | true (default) / false |
redirect_url |
no | Fallback URL used when the link is disabled or expired. Max 2048 |
curl -X POST https://shortclix.com/api/v1/projects/launch-campaign/links \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Accept: application/json" \
-H "Content-Type: application/json" \
-d '{
"original_url": "https://example.com/my-long-link",
"title": "Launch link",
"short_code": "launch"
}'
Returns 201 with the link (including short_url). Returns 422 with plan_limit_reached if you
are at your plan's link limit, or a validation error for a reserved/duplicate short_code ("This short code is already taken.") or an invalid original_url.
Destination safety: every destination URL is automatically checked against malware/phishing reputation services shortly after the link is created or its
original_urlis changed. If a destination is found to be unsafe, the short link is disabled and stops redirecting (visitors see a "blocked" page); the workspace owner is notified by e-mail. Creation itself still returns 201 — the check runs in the background — so always point links at legitimate destinations you control.
Identifying a link
For show / update / delete / QR / analytics, identify a link in one of two ways:
- By short code (recommended) – put it in the path:
GET /api/v1/links/launch - By destination URL – pass
?original_url=in the query string and use any placeholder (e.g.-) for the path segment:GET /api/v1/links/-?original_url=https%3A%2F%2Fexample.com%2Fmy-long-linkIf the URL matches more than one link, the API returns 409; use the short code instead.
Update / delete a link
PATCH /api/v1/links/{short-code}
DELETE /api/v1/links/{short-code}
PATCH accepts any subset of the create fields (e.g. change original_url, is_active, expires_at).
DELETE returns 204.
QR codes
GET /api/v1/links/{short-code}/qr
Returns the link's QR code as an SVG image (Content-Type: image/svg+xml) encoding the short URL.
curl https://shortclix.com/api/v1/links/launch/qr \
-H "Authorization: Bearer YOUR_TOKEN" \
-o launch-qr.svg
You can also identify the link by destination URL via ?original_url= (see above).
Analytics
All analytics endpoints return aggregated numbers (no chart series). Values reflect your plan's history window.
Workspace analytics (all projects)
GET /api/v1/analytics
{
"data": {
"generated_at": "2026-06-07T14:30:00+00:00",
"projects": [
{
"id": 1,
"name": "Launch Campaign",
"slug": "launch-campaign",
"stats": {
"current_month": 320,
"previous_month": 540,
"mom_change": -12.5,
"yoy_change": null
}
}
]
}
}
Project analytics (all links of a project)
GET /api/v1/projects/{id-or-slug}/analytics
Returns the project plus a links array, each with the same stats shape as above.
Link analytics (with date range)
GET /api/v1/links/{short-code}/analytics?dateFrom=2026-05-01&dateTo=2026-06-07&timezone=Europe/Vienna
| Query param | Default | Notes |
|---|---|---|
dateFrom |
start of current month | YYYY-MM-DD. Clamped to your plan's history window |
dateTo |
today | YYYY-MM-DD |
timezone |
UTC |
IANA name (e.g. Europe/Vienna); affects the day-of-week and hour breakdowns |
{
"data": {
"generated_at": "2026-06-07T14:30:00+00:00",
"link": { "id": 10, "short_code": "launch", "title": "Launch link", "original_url": "https://example.com/my-long-link" },
"date_from": "2026-05-01",
"date_to": "2026-06-07",
"timezone": "Europe/Vienna",
"period_stats": {
"total": 860,
"previous_total": 540,
"mom_change": 59.3,
"previous_out_of_range": false,
"yoy_total": null,
"yoy_change": null,
"yoy_out_of_range": null
},
"referrers": [ { "referrer": "https://t.co/", "total": 120 } ],
"countries": [ { "code": "AT", "label": "Austria", "total": 300, "pct": 34.9 } ],
"languages": [ { "code": "de", "label": "German", "total": 280, "pct": 32.6 } ],
"devices": [ { "code": "mobile", "label": "Mobile", "total": 500, "pct": 58.1 } ],
"operating_systems": [ { "code": "ios", "label": "iOS", "total": 240, "pct": 27.9 } ],
"browsers": [ { "code": "chrome", "label": "Chrome", "total": 410, "pct": 47.7 } ],
"day_of_week": [ { "day": "Mon", "total": 130, "pct": 15.1 } ],
"hours": [ { "hour": "09:00", "total": 70, "pct": 8.1 } ]
}
}
Breakdowns are sorted by
totaldescending. Clicks without a known value are bucketed as an "unverified" row.pctis the share of the period total.
Full example: track a link end-to-end
This mirrors a typical automation/AI flow: shorten a URL, get its QR code, then read its clicks later.
TOKEN="YOUR_TOKEN"
BASE="https://shortclix.com/api/v1"
# 1. Create the short link in a project
curl -s -X POST "$BASE/projects/launch-campaign/links" \
-H "Authorization: Bearer $TOKEN" -H "Accept: application/json" -H "Content-Type: application/json" \
-d '{"original_url": "https://example.com/my-long-link", "title": "My link"}'
# → { "data": { "short_code": "a1b2c3", "short_url": "https://shortclix.com/a1b2c3", ... } }
# 2. Download its QR code
curl -s "$BASE/links/a1b2c3/qr" -H "Authorization: Bearer $TOKEN" -o my-link-qr.svg
# 3. Later: how many clicks this month?
curl -s "$BASE/links/a1b2c3/analytics" -H "Authorization: Bearer $TOKEN" -H "Accept: application/json"
Field reference
Project
| Field | Type | Description |
|---|---|---|
id |
int | Unique identifier |
name |
string | Display name |
slug |
string | URL-safe identifier (unique) |
description |
string|null | Optional description |
monthly_report_recipients |
string|null | Comma-separated emails for the monthly report |
weekly_report_recipients |
string|null | Comma-separated emails for the weekly report |
short_links_count |
int | Number of links (only on list/show) |
Short link
| Field | Type | Description |
|---|---|---|
id |
int | Unique identifier |
project_id |
int | Owning project |
short_code |
string | The path of the short URL |
short_url |
string | Full short URL |
original_url |
string | Destination |
title |
string | Your label |
is_active |
bool | Whether the link is enabled |
is_effectively_active |
bool | false if disabled or expired |
redirect_url |
string|null | Fallback when disabled/expired |
expires_at |
string|null | Expiry timestamp |
Click stats (stats)
| Field | Type | Description |
|---|---|---|
current_month |
int | Clicks from the 1st of this month to today |
previous_month |
int | Clicks in the full previous month |
mom_change |
float | % change vs. the same period last month |
yoy_change |
float|null | % change vs. last year (Pro plans with ≥24 months history) |
Connect via MCP
SHORTCLIX also speaks MCP (Model Context Protocol), so AI assistants (Claude, and other MCP-capable
clients) can manage your links and read analytics in natural language — "track this link", "how many clicks
did it get?". MCP is available on the Basic and Pro plans. For the full step-by-step setup (Claude Code,
Claude Desktop, local vs. production), see /docs/mcp.
- Endpoint:
https://shortclix.com/mcp - Auth: the same tokens as the REST API (created in Workspace Settings → API Tokens). Use a read & write token if you want the assistant to create or change links; a read-only token limits it to listing and analytics.
Client configuration
Most MCP clients accept an HTTP server entry like this (replace the placeholder with one of your tokens):
{
"mcpServers": {
"shortclix": {
"type": "http",
"url": "https://shortclix.com/mcp",
"headers": {
"Authorization": "Bearer YOUR_TOKEN_HERE"
}
}
}
}
The exact config location depends on your client. The dashboard shows this snippet pre-filled with your endpoint in Workspace Settings.
Available tools
The assistant gets the full set, mirroring the REST API:
- Projects:
list_projects,create_project,update_project,delete_project - Short links:
list_short_links,create_short_link,update_short_link,delete_short_link,get_qr_code - Analytics:
get_workspace_analytics,get_project_analytics,get_link_analytics
Everything is scoped to the token's workspace and constrained by your plan's limits. Creating, updating and deleting require a read & write token.
Questions or higher limits? Contact support at hello@shortclix.com.