ShortSwitch

API Reference

Full REST API for link management, analytics, webhooks, and account configuration. Includes the legacy XML/simple-text API for existing integrations.

Authentication

Two methods. JWT is preferred for new integrations. API key is the legacy method and is supported everywhere.

JWT Bearer (recommended)

Exchange email + password for a 7-day JWT. Pass it as Authorization: Bearer <token> on all subsequent requests.

POST /api/auth/jwt
{ "email": "you@example.com", "password": "secret" }
→ { "token": "eyJ..." }

Token payload: { userId, accountId }. Account context is fixed at issuance time to the domain used for login.

API Key (legacy)

Append ?apiKey=<key> to any request. Find your key at Settings → Security → API Key.

GET /api/links?apiKey=abc123...

API keys are SHA1 hex strings. Regenerating invalidates the old key immediately.


Base URL & Response Formats

All REST endpoints return JSON. The legacy API supports XML (default), JSON, and plain-text.

REST API base: https://app.shortswitch.com

Content-Type: application/json for all request bodies.

Legacy format selection: append ?format=json, ?format=xml, or ?format=simple. Default is xml.


Error Handling

REST API returns standard HTTP status codes with a JSON body. Legacy API returns an error code in the response envelope regardless of HTTP status.

REST error response

HTTP 400
{ "message": "account.domain is required" }

Legacy error response (JSON)

{ "errorCode": "201",
  "errorMessage": "Missing parameter(s)",
  "statusCode": "ERROR" }

Create, read, update, and delete short links. All endpoints require authentication.

GET /api/links 🔒 auth required

List links for the current account. Supports pagination and search.

ParameterTypeDescription
q optional string Full-text search across token, URL, description
page optional integer Page number (default 1, 20 per page)
sort optional string lastCreated | byHits | todaysLinks | tokenMatch
GET /api/links/recent 🔒 auth required

Returns the 10 most recently created links.

GET /api/links/popular 🔒 auth required

Returns the 10 most-clicked links in the last 30 days.

GET /api/links/search 🔒 auth required

Search links by token, URL, or description.

ParameterTypeDescription
q required string Search term
POST /api/links 🔒 auth required

Create a new short link. If allow_duplicate_urls is false (default), returns the existing link when the same URL already exists.

ParameterTypeDescription
url required string Destination URL
token optional string Custom slug. Random Base58 generated if omitted.
description optional string
redirectCode optional integer 301 or 302 (default 301)
passThrough optional boolean Append incoming query params to destination
expiresAt optional datetime ISO 8601. Link becomes inactive after this time.
expiredUrl optional string Redirect destination after expiry
password optional string Bcrypt-hash stored; visitor must enter this password
campaignId optional integer Associate a campaign (pixels + analytics tags)
overridePixelIds optional integer[] Per-link pixel overrides (replaces campaign pixels)
geoDestinations optional object Map of ISO 3166-1 alpha-2 country code → destination URL
deviceDestinations optional object Keys: mobile, tablet, desktop, smarttv → destination URL
abVariants optional object[] A/B test variants: [{ url, weight, label? }]
{ "url": "https://example.com/page", "token": "promo24", "redirectCode": 302 }
← { "id": 42, "token": "promo24", "shortUrl": "https://go.yourdomain.com/promo24", "url": "..." }
GET /api/links/:id 🔒 auth required

Get a single link by numeric ID.

ParameterTypeDescription
id required integer Link ID
PUT /api/links/:id 🔒 auth required

Update a link. All fields are optional; only supplied fields are changed.

ParameterTypeDescription
url optional string New destination URL
token optional string New custom slug (must be unique within account)
description optional string
redirectCode optional integer 301 or 302
passThrough optional boolean
expiresAt optional datetime ISO 8601 or null to clear
expiredUrl optional string
password optional string Set new password, or null to remove
campaignId optional integer null to remove campaign association
overridePixelIds optional integer[]
geoDestinations optional object null to clear all geo rules
deviceDestinations optional object null to clear all device rules
abVariants optional object[] null to clear A/B test
DELETE /api/links/:id 🔒 auth required

Delete a link permanently.

ParameterTypeDescription
id required integer Link ID
GET /api/links/:id/chart_data 🔒 auth required

Daily click counts for a link. Returns an array of { date, clicks } objects from link creation to today.

ParameterTypeDescription
id required integer Link ID
← [{ "date": "2025-06-01", "clicks": 42 }, ...]
GET /api/links/:id/qr_image 🔒 auth required

QR code image for the link's short URL.

ParameterTypeDescription
id required integer Link ID
format optional string png (default) or svg
size optional integer Pixel width (default 200)
GET /api/links.csv 🔒 auth required

Export all links as a CSV file. Columns: Long URL, Domain, Token, Created By, Created At, Total Visits, Description, HTTP Status Code, Allow Parameter Pass Through.

POST /api/links/import 🔒 auth required

Bulk import links from a CSV or TSV file. Column 0 = URL, Column 1 = token (optional). Multipart form upload; field name: file.

GET /api/links/:id/routing 🔒 auth required

Get geo, device, and A/B routing rules for a link.

ParameterTypeDescription
id required integer Link ID

Pixels & Analytics Tags

Retargeting pixels and analytics tags fire from an interstitial page on redirect — before the visitor reaches the destination. Supported platforms: Facebook, Google Ads, LinkedIn, TikTok, Pinterest, Twitter/X, Snapchat (pixels); GA4, Segment, Matomo, Plausible, Fathom, Mixpanel (analytics tags).

GET /api/pixels 🔒 auth required

List all retargeting pixels configured for the account.

POST /api/pixels 🔒 auth required

Add a retargeting pixel. Paste the full platform snippet — the server extracts the pixel ID; the raw snippet is discarded.

ParameterTypeDescription
platform required string facebook | google_ads | linkedin | tiktok | pinterest | twitter | snapchat | custom
name required string Display label
snippet required string Full platform snippet (ID is extracted server-side)
{ "platform": "facebook", "name": "Main FB pixel", "snippet": "fbq('init', '123456789')" }
← { "id": 3, "platform": "facebook", "name": "Main FB pixel", "pixelId": "123456789" }
DELETE /api/pixels/:id 🔒 auth required

Remove a pixel. Existing link associations are cleared.

ParameterTypeDescription
id required integer
GET /api/analytics-tags 🔒 auth required

List all analytics tags configured for the account.

POST /api/analytics-tags 🔒 auth required

Add an analytics tag. Paste the full platform snippet.

ParameterTypeDescription
platform required string ga4 | segment | matomo | plausible | fathom | mixpanel | custom
name required string Display label
snippet required string Full platform snippet
DELETE /api/analytics-tags/:id 🔒 auth required

Remove an analytics tag.

ParameterTypeDescription
id required integer

Campaigns

Campaigns bundle pixels and analytics tags that fire together on redirect. Associate a campaign with a link to fire all its tags on every click from that link.

GET /api/campaigns 🔒 auth required

List all campaigns.

GET /api/campaigns/:id 🔒 auth required

Get a single campaign with its associated pixels and analytics tags.

ParameterTypeDescription
id required integer
POST /api/campaigns 🔒 auth required

Create a campaign.

ParameterTypeDescription
name required string Display label
pixelIds optional integer[] Pixel IDs to include
analyticsTagIds optional integer[] Analytics tag IDs to include
{ "name": "Summer 2025", "pixelIds": [1,3], "analyticsTagIds": [2] }
PUT /api/campaigns/:id 🔒 auth required

Update a campaign name or its pixel/tag associations.

ParameterTypeDescription
name optional string
pixelIds optional integer[] Replaces existing pixel list
analyticsTagIds optional integer[] Replaces existing analytics tag list
DELETE /api/campaigns/:id 🔒 auth required

Delete a campaign. Existing link associations are cleared.

ParameterTypeDescription
id required integer

Webhooks

Receive real-time click events at any HTTP endpoint. Deliveries are HMAC-SHA256 signed and retried up to 5 times with exponential backoff (1 min → 5 min → 30 min → 2 hr → 8 hr).

GET /api/account/webhooks 🔒 auth required

List all webhooks for the account.

POST /api/account/webhooks 🔒 auth required

Create a webhook. A secret is auto-generated and returned once — store it immediately.

ParameterTypeDescription
url required string HTTPS endpoint to receive events
events optional string[] Event types to subscribe to. Default: ["click"]
{ "url": "https://yourapp.com/hooks/shortswitch", "events": ["click"] }
← { "id": 1, "url": "...", "secret": "whsec_...", "events": ["click"] }
PUT /api/account/webhooks/:id 🔒 auth required

Update a webhook.

ParameterTypeDescription
url optional string
events optional string[]
enabled optional boolean
POST /api/account/webhooks/:id/rotate-secret 🔒 auth required

Generate a new HMAC secret. The old secret is invalidated immediately.

ParameterTypeDescription
id required integer
DELETE /api/account/webhooks/:id 🔒 auth required

Delete a webhook and all its delivery history.

ParameterTypeDescription
id required integer
Click event payload
{
  "event":      "click",
  "timestamp":  "2025-06-01T14:22:00.000Z",
  "account_id": 42,
  "link": {
    "id":          1234,
    "token":       "promo24",
    "destination": "https://www.example.com/page",
    "domain":      "go.yourdomain.com"
  },
  "click": {
    "country":         "US",
    "subdivision":     "CA",
    "city":            "San Francisco",
    "device_type":     "desktop",
    "referrer_domain": "google.com",
    "user_agent":      "Mozilla/5.0 ..."
  }
}

All geo and referrer fields are null if unavailable. Verify the signature: sha256=HMAC-SHA256(secret, rawBody) in the X-ShortSwitch-Signature header.


Account & Domains

Manage account settings and custom short-link domains. Domain management requires account admin role.

GET /api/account 🔒 auth required

Get current account settings and subscription state.

PUT /api/account 🔒 auth required

Update account settings.

ParameterTypeDescription
name optional string Account display name
allowDuplicateUrls optional boolean Allow multiple tokens for the same URL
brandedRedirectType optional string toolbar | interstitial
customInvalidUrl optional string Redirect target for invalid tokens
enableToolbar optional boolean Requires subscription feature gate
homepageRedirectUrl optional string Redirect for bare domain requests
prependPathSupport optional boolean
prependPath optional string Path prefix for short URLs
useCaseInsensitiveTokens optional boolean
restrictUrlSchemes optional boolean Only allow http/https/ftp/mailto
filterUrls optional boolean Enable SURBL spam check on link creation
toolbarHtml optional string Custom HTML for branded toolbar
toolbarStyling optional string Inline CSS for toolbar
toolbarStylingUrl optional string External CSS URL for toolbar
toolbarTitle optional string
GET /api/account/stats 🔒 auth required

Total link count and visit count for the account.

GET /api/account/domains 🔒 auth required

List all custom short-link domains for the account.

POST /api/account/domains 🔒 auth required

Add a new custom domain. If a CloudFront distribution is already deployed for this account, a full reprovision is triggered automatically (new ACM cert with all domains as SANs).

ParameterTypeDescription
domain required string e.g. go.yourdomain.com
← { "domain": { "id": 5, "domain": "go.yourdomain.com" }, "provisioning": true }
DELETE /api/account/domains/:domain 🔒 auth required

Remove a domain. Cannot remove the last domain on an account.

ParameterTypeDescription
domain required string Domain value (not ID)
PATCH /api/account/domains/:id/primary 🔒 auth required

Set a domain as the primary domain for permalink generation.

ParameterTypeDescription
id required integer
GET /api/account/cloudfront-status 🔒 auth required

Get the current CloudFront provisioning status for this account.


Legacy API

Drop-in compatible with integrations built against the original API. Authenticates via ?apiKey=<key>. Default response format is XML; pass ?format=json or ?format=simple (plain text) to change.

Standard XML envelope
<?xml version="1.0" encoding="UTF-8"?>
<shortSwitch>
  <errorCode>0</errorCode>
  <errorMessage/>
  <statusCode>OK</statusCode>
  <results>
    <shortUrl>https://go.yourdomain.com/abc123</shortUrl>
    <longUrl>https://www.example.com/long/path</longUrl>
    <hash>abc123</hash>
  </results>
</shortSwitch>

Shorten / Create

POST /shorten

Shorten a URL. Also available as GET. Aliases: /create.

ParameterTypeDescription
longUrl / url required string Destination URL
token / hash optional string Custom slug
domain optional string Override account primary domain
passThrough optional boolean Pass incoming query params to destination
apiKey required string User API key
format optional string json | xml | simple
← { "results": { "shortUrl": "...", "longUrl": "...", "hash": "abc123" } }
/* simple format: returns just the short URL as plain text */

Expand / Info / Stats

GET /expand

Expand a short URL to its destination.

ParameterTypeDescription
hash / token / permalink / shortUrl required string Any form of the short URL or just the token
apiKey required string
← { "results": { "longUrl": "https://www.example.com/..." } }
GET /info

Get metadata about a short link.

ParameterTypeDescription
hash / token required string
keys optional string Comma-separated field names to include in results
apiKey required string
← { "results": { "hash": "abc123", "longUrl": "...", "shortUrl": "...", "shortenedByUser": "Jane" } }
GET /stats

Get lifetime click count for a short link.

ParameterTypeDescription
hash / token required string
apiKey required string
← { "results": { "hash": "abc123", "clicks": 1042 } }
GET /validate

Validate whether a URL and/or token is acceptable without creating a link.

ParameterTypeDescription
longUrl / url required string
token optional string
apiKey required string
GET /errors

Returns the full error code dictionary as a list of { code, message } objects.

ParameterTypeDescription
apiKey required string

List / Delete

GET /list

List short links. By default lists all links for the account. Pass ?account=no to list only the authenticated user's links.

ParameterTypeDescription
account optional string Pass "no" to filter to current user's links only
apiKey required string
← { "results": { "links": [...], "count": 42 } }
DELETE /delete

Delete a short link.

ParameterTypeDescription
hash / token required string
apiKey required string

Legacy Error Codes

CodeMessage
0 OK
201 Missing parameter(s)
203 You must be authenticated
205 Invalid API key
208 There was a problem creating your shortened link
209 Your account must be confirmed
1204 %s is not a valid ShortSwitch hash
1206 URL already shortened
1212 Custom keyword already in use
1213 Could not find long URL for that short URL

Questions? Contact us or check the @simplewebauthn docs for WebAuthn integration help.