CompactSaaS Links API Reference

Complete API reference for the CompactSaaS Links service. The Links API provides URL redirect management, short link generation, and custom domain configuration with managed TLS.


Base URL

The Links API is available through the CompactSaaS External API, the same endpoint used for analytics tracking.

EnvironmentBase URL
Productionhttps://api.compactsaas.com/v1
Staginghttps://api.compactsaasstaging.click/v1

All endpoints are under the /v1/links/ prefix. The team is identified automatically from your API key — no team ID in the URL.


Authentication

All endpoints require an API key in the x-api-key header.

x-api-key: pk_live_<32 random characters>

API keys can be created from the CompactSaaS dashboard under API Keys in the sidebar. Each key is bound to a team — all operations are scoped to that team automatically.

Error Responses

StatusBodyCause
401{"message": "Unauthorized"}Missing, invalid, or revoked API key
403{"message": "Forbidden"}Account disabled or suspended

Error Format

The API returns errors in two formats depending on the error type:

Validation Errors (request schema violations)

{
  "errors": [
    { "param": "sourceDomain", "type": "String must contain at least 1 character(s)" },
    { "param": "targetUrl", "type": "Invalid url" }
  ]
}

Business Logic Errors

{
  "errors": "validation_error"
}

Common error codes:

CodeHTTP StatusDescription
validation_error400Business rule violation (e.g., unverified domain, duplicate redirect)
not_found404Resource does not exist
unauthorized401Authentication required
not_member403User is not a team member
internal_server_error500Unexpected server error

Timestamps

All timestamp fields (createdAt, updatedAt, verifiedAt) are Unix epoch milliseconds (e.g., 1772970450599).


Redirects

Redirects map a source domain + path to a target URL. When a request hits the CloudFront edge network matching {sourceDomain}{sourcePath}, it returns an HTTP redirect (301 or 302) to the targetUrl.

Redirects are served at the edge via CloudFront Functions backed by a Key-Value Store (KVS), so they execute in under 1ms with no origin round-trip.


Create Redirect

Creates a new redirect rule and immediately syncs it to the edge network.

POST /v1/links/redirects

Request Body

FieldTypeRequiredDefaultDescription
sourceDomainstringYesThe domain to match. Must be a platform domain (e.g., links.compactsaasstaging.click) or a verified custom domain. Min 1, max 253 characters.
sourcePathstringNo"/"The URL path to match. Must start with /. Min 1, max 2048 characters.
targetUrlstringYesThe destination URL. Must be a valid URL. Max 2048 characters.
statusCodeintegerNo301HTTP redirect status code. Must be 301 (Moved Permanently) or 302 (Found).
ttlintegerNo86400Cache TTL in seconds for the redirect response at the edge. Min 0, max 31536000 (1 year).
analyticsEnabledbooleanNofalseEnable click analytics. When enabled, clicks are tracked as pageviews in the analytics dashboard and billed via the advanced_analytics_pageviews meter.

Example Request

curl -X POST https://api.compactsaas.com/v1/links/redirects \
  -H "x-api-key: pk_live_your_key_here" \
  -H "Content-Type: application/json" \
  -d '{
    "sourceDomain": "links.genairumors.com",
    "sourcePath": "/hello",
    "targetUrl": "https://compactsaas.com",
    "statusCode": 301,
    "ttl": 86400
  }'

Response — 201 Created

{
  "redirect": {
    "id": "01KK6MC7N71NTJ7XHJKRMR119V",
    "sourceDomain": "links.compactsaasstaging.click",
    "sourcePath": "/doc-test",
    "targetUrl": "https://example.com/doc-test",
    "statusCode": 302,
    "ttl": 3600,
    "enabled": true,
    "analyticsEnabled": false,
    "analyticsWebsiteId": null,
    "createdAt": 1772970450599,
    "updatedAt": 1772970450599
  }
}

Errors

StatusCodeCause
400validation_errorsourceDomain is not a platform domain and is not verified for this team
400validation_errorA redirect already exists for this sourceDomain + sourcePath combination
400(array)Request body fails schema validation

List Redirects

Returns all redirects for the team.

GET /v1/links/redirects

Example Request

curl https://api.compactsaas.com/v1/links/redirects \
  -H "x-api-key: pk_live_your_key_here"

Response — 200 OK

{
  "redirects": [
    {
      "id": "01KK6E10671WWMNV9RWA2ZKGQE",
      "sourceDomain": "links.genairumors.com",
      "sourcePath": "/hello",
      "targetUrl": "https://compactsaas.com",
      "statusCode": 301,
      "ttl": 86400,
      "enabled": true,
      "analyticsEnabled": false,
      "analyticsWebsiteId": null,
      "createdAt": 1772963791047,
      "updatedAt": 1772963791047
    }
  ]
}

Returns an empty array if no redirects exist: {"redirects": []}.


Update Redirect

Updates an existing redirect. Only the fields provided in the request body are changed. The edge KVS entry is re-synced immediately.

PUT /v1/links/redirects/{redirectId}

Path Parameters

ParameterDescription
redirectIdThe redirect's id field (ULID)

Request Body

All fields are optional. Only provided fields are updated.

FieldTypeDescription
targetUrlstringNew destination URL. Must be a valid URL. Max 2048 characters.
statusCodeintegerNew HTTP status code. Must be 301 or 302.
ttlintegerNew cache TTL in seconds. Min 0, max 31536000.
enabledbooleanEnable or disable the redirect. Disabled redirects are removed from the edge.
analyticsEnabledbooleanEnable or disable click analytics.

Example Request

curl -X PUT https://api.compactsaas.com/v1/links/redirects/01KK6MC7N71NTJ7XHJKRMR119V \
  -H "x-api-key: pk_live_your_key_here" \
  -H "Content-Type: application/json" \
  -d '{"targetUrl": "https://example.com/updated", "statusCode": 301}'

Response — 200 OK

{
  "redirect": {
    "id": "01KK6MC7N71NTJ7XHJKRMR119V",
    "sourceDomain": "links.compactsaasstaging.click",
    "sourcePath": "/doc-test",
    "targetUrl": "https://example.com/updated",
    "statusCode": 301,
    "ttl": 3600,
    "enabled": true,
    "analyticsEnabled": false,
    "analyticsWebsiteId": null,
    "createdAt": 1772970450599,
    "updatedAt": 1772970467719
  }
}

Errors

StatusCodeCause
404not_foundRedirect does not exist or does not belong to this team

Delete Redirect

Permanently deletes a redirect and removes it from the edge KVS.

DELETE /v1/links/redirects/{redirectId}

Example Request

curl -X DELETE https://api.compactsaas.com/v1/links/redirects/01KK6MC7N71NTJ7XHJKRMR119V \
  -H "x-api-key: pk_live_your_key_here"

Response — 204 No Content

Empty response body.

Errors

StatusCodeCause
404not_foundRedirect does not exist or does not belong to this team

Short Links

Short links generate a compact URL on the platform's short domain (e.g., staging.urlz.zip in staging, urlz.zip in production). Each short link gets a unique 7-character base62 code, or you can specify a custom code.

Short links are served at the edge identically to redirects — via CloudFront Functions and KVS.


Create Short Link

Creates a new short link with either an auto-generated or custom short code.

POST /v1/links/shorten

Request Body

FieldTypeRequiredDescription
targetUrlstringYesThe destination URL. Must be a valid URL. Max 2048 characters.
customCodestringNoCustom short code. 3–32 characters, alphanumeric plus - and _ only (/^[a-zA-Z0-9_-]+$/). If omitted, a random 7-character base62 code is generated.
domainstringNoCustom domain for the short link. Must be a verified and active custom domain for your team. If omitted, uses the platform default domain (urlz.zip).
analyticsEnabledbooleanNoEnable click analytics. When enabled, clicks are tracked as pageviews in the analytics dashboard.

Example Request — Auto-generated Code

curl -X POST https://api.compactsaas.com/v1/links/shorten \
  -H "x-api-key: pk_live_your_key_here" \
  -H "Content-Type: application/json" \
  -d '{"targetUrl": "https://example.com/my-long-page"}'

Response — 201 Created

{
  "link": {
    "id": "01KK6MCSFTTM0GPJB3XEBWJACY",
    "shortCode": "oTmGvkP",
    "shortUrl": "https://staging.urlz.zip/oTmGvkP",
    "targetUrl": "https://example.com/short-test",
    "domain": "staging.urlz.zip",
    "enabled": true,
    "analyticsEnabled": false,
    "analyticsWebsiteId": null,
    "hasClicks": false,
    "createdAt": 1772970468859,
    "updatedAt": 1772970468859
  }
}

Example Request — Custom Code

curl -X POST https://api.compactsaas.com/v1/links/shorten \
  -H "x-api-key: pk_live_your_key_here" \
  -H "Content-Type: application/json" \
  -d '{"targetUrl": "https://example.com/promo", "customCode": "summer-sale"}'

Response — 201 Created

{
  "link": {
    "id": "01KK6MCT06Q29ZSQAXT4RSK3P4",
    "shortCode": "summer-sale",
    "shortUrl": "https://staging.urlz.zip/summer-sale",
    "targetUrl": "https://example.com/promo",
    "domain": "staging.urlz.zip",
    "enabled": true,
    "analyticsEnabled": false,
    "analyticsWebsiteId": null,
    "hasClicks": false,
    "createdAt": 1772970469382,
    "updatedAt": 1772970469382
  }
}

Errors

StatusCodeCause
400validation_errorCustom code already in use
400(array)Request body fails schema validation

List Short Links

Returns all short links for the team.

GET /v1/links/short

Example Request

curl https://api.compactsaas.com/v1/links/short \
  -H "x-api-key: pk_live_your_key_here"

Response — 200 OK

{
  "links": [
    {
      "id": "01KK6MCSFTTM0GPJB3XEBWJACY",
      "shortCode": "oTmGvkP",
      "shortUrl": "https://staging.urlz.zip/oTmGvkP",
      "targetUrl": "https://example.com/short-test",
      "domain": "staging.urlz.zip",
      "enabled": true,
      "analyticsEnabled": false,
      "analyticsWebsiteId": null,
      "hasClicks": false,
      "createdAt": 1772970468859,
      "updatedAt": 1772970468859
    }
  ]
}

Returns an empty array if no short links exist: {"links": []}.


Get Short Link

Returns a single short link by ID.

GET /v1/links/short/{linkId}

Path Parameters

ParameterDescription
linkIdThe short link's id field (ULID)

Example Request

curl https://api.compactsaas.com/v1/links/short/01KK6MCSFTTM0GPJB3XEBWJACY \
  -H "x-api-key: pk_live_your_key_here"

Response — 200 OK

{
  "link": {
    "id": "01KK6MCSFTTM0GPJB3XEBWJACY",
    "shortCode": "oTmGvkP",
    "shortUrl": "https://staging.urlz.zip/oTmGvkP",
    "targetUrl": "https://example.com/short-test",
    "domain": "staging.urlz.zip",
    "enabled": true,
    "analyticsEnabled": false,
    "analyticsWebsiteId": null,
    "hasClicks": false,
    "createdAt": 1772970468859,
    "updatedAt": 1772970468859
  }
}

Returns 404 NOT_FOUND if the link does not exist.


Get Short Link Stats

Returns daily click timeseries data for a short link. Data comes from analytics rollups which are preserved permanently, regardless of the raw event retention policy. Requires analyticsEnabled on the link.

GET /v1/links/short/{linkId}/stats

Path Parameters

ParameterDescription
linkIdThe short link's id field (ULID)

Query Parameters

ParameterTypeDefaultDescription
daysinteger30Trailing days to include (1–730)

Example Request

curl "https://api.compactsaas.com/v1/links/short/01KK6MCSFTTM0GPJB3XEBWJACY/stats?days=14" \
  -H "x-api-key: pk_live_your_key_here"

Response — 200 OK

{
  "linkId": "01KK6MCSFTTM0GPJB3XEBWJACY",
  "totalClicks": 42,
  "days": 14,
  "timeseries": [
    { "date": "2026-03-08", "clicks": 3 },
    { "date": "2026-03-09", "clicks": 5 },
    { "date": "2026-03-15", "clicks": 10 },
    { "date": "2026-03-16", "clicks": 24 }
  ]
}

Returns 404 NOT_FOUND if the link does not exist. Returns totalClicks: 0 and empty timeseries if analytics is not enabled on the link or the analytics table is unavailable.


Update Short Link

Updates an existing short link. Only the fields provided in the request body are changed. If targetUrl is changed, the edge KVS entry is re-synced immediately.

PUT /v1/links/short/{linkId}

Path Parameters

ParameterDescription
linkIdThe short link's id field (ULID)

Request Body

All fields are optional. Only provided fields are updated.

FieldTypeDescription
targetUrlstringNew destination URL. Must be a valid URL. Max 2048 characters.
analyticsEnabledbooleanEnable or disable click analytics.

Example Request

curl -X PUT https://api.compactsaas.com/v1/links/short/01KK6MCSFTTM0GPJB3XEBWJACY \
  -H "x-api-key: pk_live_your_key_here" \
  -H "Content-Type: application/json" \
  -d '{"analyticsEnabled": true}'

Response — 200 OK

{
  "link": {
    "id": "01KK6MCSFTTM0GPJB3XEBWJACY",
    "shortCode": "oTmGvkP",
    "shortUrl": "https://staging.urlz.zip/oTmGvkP",
    "targetUrl": "https://example.com/short-test",
    "domain": "staging.urlz.zip",
    "enabled": true,
    "analyticsEnabled": true,
    "analyticsWebsiteId": "01KK6MD0A1B2C3D4E5F6G7H8J9",
    "hasClicks": true,
    "createdAt": 1772970468859,
    "updatedAt": 1772970512000
  }
}

Errors

StatusCodeCause
404not_foundShort link does not exist or does not belong to this team

Delete Short Link

Permanently deletes a short link and removes it from the edge KVS.

DELETE /v1/links/short/{linkId}

Path Parameters

ParameterDescription
linkIdThe short link's id field (ULID)

Example Request

curl -X DELETE https://api.compactsaas.com/v1/links/short/01KK6MCSFTTM0GPJB3XEBWJACY \
  -H "x-api-key: pk_live_your_key_here"

Response — 204 No Content

Empty response body.


Get QR Code

Generate a QR code for a short link. Returns the QR code image directly (not JSON). The response is cacheable — identical requests return the same image.

Every short link automatically has a QR code endpoint. No creation limits, no branding restrictions.

GET /v1/links/short/{linkId}/qr

Path Parameters

ParameterDescription
linkIdThe short link's id field (ULID)

Query Parameters

All query parameters are optional.

ParameterTypeDefaultDescription
formatsvg | pngsvgImage format. SVG is ~1.5KB, PNG is ~2KB at 300px
size1001000300Image dimensions in pixels
colorhex color#000000QR code foreground color
bgColorhex color#ffffffQR code background color

Example Request — Default SVG

curl https://api.compactsaas.com/v1/links/short/01KK6MCSFTTM0GPJB3XEBWJACY/qr \
  -H "x-api-key: pk_live_your_key_here" \
  -o qr-code.svg

Example Request — Custom Branded PNG

curl "https://api.compactsaas.com/v1/links/short/01KK6MCSFTTM0GPJB3XEBWJACY/qr?format=png&size=500&color=%23FF6600&bgColor=%23FFFFFF" \
  -H "x-api-key: pk_live_your_key_here" \
  -o qr-code.png

Response

Returns the image directly with appropriate Content-Type header:

  • SVG: Content-Type: image/svg+xml
  • PNG: Content-Type: image/png

Response includes Cache-Control: public, max-age=86400 for edge caching.

QR Code Analytics

When a short link has analyticsEnabled: true, every QR code scan is automatically tracked in your analytics dashboard. QR scans appear as "Direct / QR" traffic — distinguishable from regular link clicks which show the referring page.

No additional setup required. Create a short link with analytics enabled, download the QR code, and every scan shows up alongside your website traffic.

Errors

StatusErrorCause
404Short link not foundInvalid linkId or link belongs to another team

Custom Domains

Custom domains allow your team to serve redirects from your own domain (e.g., links.yourcompany.com) with fully managed TLS certificates.

Domain setup (verification, activation, TLS provisioning) is done through the CompactSaaS dashboard. Once a domain is active, you can manage it programmatically via this API:

  • List domains — see all your custom domains and their status
  • Set fallback URL — configure where unmatched paths redirect to (instead of 403)

Domain Lifecycle

Dashboard: Verify → Check DNS → Activate → Wait for TLS → Active
API:       List domains (read-only) | Set fallback URL (active domains only)

Set Domain Fallback URL

Configures a fallback redirect URL for a custom domain. When a request arrives at your custom domain for a path that has no matching redirect rule, the fallback URL is used instead of returning a raw 403 error from the origin.

The fallback is served as a 302 Found redirect at the edge.

The domain must have tenantStatus: "active".

POST /v1/links/domains/fallback

Request Body

FieldTypeRequiredDescription
domainstringYesThe active custom domain.
fallbackUrlstringYesThe URL to redirect unmatched paths to. Must be a valid URL. Send an empty string "" or null to clear the fallback.

Example Request — Set Fallback

curl -X POST https://api.compactsaas.com/v1/links/domains/fallback \
  -H "x-api-key: pk_live_your_key_here" \
  -H "Content-Type: application/json" \
  -d '{"domain": "links.yourcompany.com", "fallbackUrl": "https://yourcompany.com"}'

Response — 200 OK

{
  "domain": {
    "domain": "links.yourcompany.com",
    "status": "verified",
    "tenantStatus": "active",
    "fallbackUrl": "https://yourcompany.com",
    "verifiedAt": 1772836089453,
    "createdAt": 1772836027575
  }
}

Example Request — Clear Fallback

curl -X POST https://api.compactsaas.com/v1/links/domains/fallback \
  -H "x-api-key: pk_live_your_key_here" \
  -H "Content-Type: application/json" \
  -d '{"domain": "links.yourcompany.com", "fallbackUrl": ""}'

Errors

StatusCodeCause
404not_foundNo verification record exists for this domain and team
400validation_errorDomain is not yet active (tenantStatus must be "active")

List Domain Verifications

Returns all domain verification records for the team, including their current status and tenant information.

GET /v1/links/domains

Example Request

curl https://api.compactsaas.com/v1/links/domains \
  -H "x-api-key: pk_live_your_key_here"

Response — 200 OK

{
  "domains": [
    {
      "domain": "links.genairumors.com",
      "status": "verified",
      "tenantStatus": "active",
      "fallbackUrl": "https://genairumors.com",
      "verifiedAt": 1772836089453,
      "createdAt": 1772836027575
    }
  ]
}

Returns an empty array if no domains are configured: {"domains": []}.

Domain Object

FieldTypeDescription
domainstringThe custom domain name.
statusstringDNS verification status: "pending", "verified", or "failed".
tenantStatusstring | nullTenant provisioning status: "creating", "active", "failed", or null.
fallbackUrlstring | nullFallback redirect URL for unmatched paths. null if not configured.
verifiedAtnumber | nullTimestamp (ms) when DNS was verified. null if not yet verified.
createdAtnumberTimestamp (ms) when the record was created.

API Endpoint Summary

MethodEndpointDescription
POST/v1/links/redirectsCreate a redirect
GET/v1/links/redirectsList all redirects
PUT/v1/links/redirects/{redirectId}Update a redirect
DELETE/v1/links/redirects/{redirectId}Delete a redirect
POST/v1/links/shortenCreate a short link
GET/v1/links/shortList all short links
DELETE/v1/links/short/{linkId}Delete a short link
GET/v1/links/domainsList custom domains
POST/v1/links/domains/fallbackSet/clear fallback URL

Domain setup (verification, activation, TLS provisioning) is managed through the CompactSaaS dashboard.


Dashboard API — Unified Links

These endpoints are used by the CompactSaaS dashboard (Cognito JWT auth, not API key auth). They provide a unified view across both redirects and short links.

List All Links

GET /:teamId/links/all

Returns both redirects and short links in a single array. Each item has a type field ("redirect" or "shortlink") and a sourceUrl field.

Query Parameters:

ParamTypeDescription
typeredirect | shortlinkFilter by link type
searchstringCase-insensitive substring match on sourceUrl, targetUrl, or shortCode
sortcreated | updatedSort field (default: created)
orderasc | descSort order (default: desc)

Get Link Detail

GET /:teamId/links/detail/:linkId

Returns a single link by ID. Tries short link first, then redirect (two point Gets, no scan). Returns 404 if neither exists.

Response includes all fields for the link type plus type and sourceUrl.

List All Links (External API)

GET /v1/links

Same as the dashboard GET /:teamId/links/all but uses API key auth. Team is determined from the API key.

Query Parameters: Same as dashboard — type, search, sort, order.

Get Link Detail (External API)

GET /v1/links/:linkId

Same as the dashboard GET /:teamId/links/detail/:linkId but uses API key auth. Returns 404 if neither a short link nor redirect exists with the given ID.

Need the interactive API? Open the API Explorer.
Web analytics, short links, QR codes, bio pages, and wallet passes. Built in Sydney, Australia.
© Copyright 2026 CompactSaaS. All Rights Reserved.