CompactSaaS External API Reference

Complete API reference for the CompactSaaS External API. For a quick introduction, see the Getting Started Guide.


Base URLs

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

Authentication

All endpoints except /v1/health require an API key in the x-api-key header.

API Key Format

x-api-key: pk_live_<32 random characters>
  • Production keys: pk_live_... (40 characters total)
  • Staging/Test keys: pk_test_... (40 characters total)

Obtaining an API Key

  1. Log in to your CompactSaaS Dashboard
  2. Navigate to Team SettingsAPI Keys
  3. Click Create API Key
  4. Save the key securely (shown only once)

Key Limits

  • Maximum 2 API keys per team
  • Keys can be revoked immediately from the dashboard
  • Revoked keys return 401 Unauthorized

Example Authenticated Request

curl -X POST https://api.compactsaas.com/v1/track \
  -H "x-api-key: pk_live_a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6" \
  -H "Content-Type: application/json" \
  -d '{"event": "page_view", "properties": {"page": "/home"}}'

Rate Limits

Rate limits protect the API infrastructure from abuse. They are not billing limits.

LimitValueDescription
Requests per second100Sustained request rate
Burst limit200Maximum burst capacity
Monthly quotaNonePay-as-you-go billing

Rate Limit Headers

When rate limited, the API returns:

  • Status: 429 Too Many Requests
  • Header: Retry-After: <seconds> - Time to wait before retrying

Rate Limit Response

{
  "error": "Too Many Requests",
  "message": "Rate limit exceeded. Please retry after the specified time.",
  "code": "RATE_LIMIT_EXCEEDED"
}

Best Practices

  • Implement exponential backoff for retries
  • Respect the Retry-After header
  • Batch events when possible to reduce request count
  • Monitor your request rate in the dashboard

Endpoints

MethodPathDescription
POST/v1/trackTrack an analytics event
GET/v1/healthHealth check
POST/v1/links/redirectsCreate a redirect
GET/v1/links/redirectsList redirects
PUT/v1/links/redirects/:idUpdate a redirect
DELETE/v1/links/redirects/:idDelete a redirect
POST/v1/links/shortenCreate a short link
GET/v1/links/shortList short links
GET/v1/links/short/:idGet a short link
GET/v1/links/short/:id/statsGet click statistics
PUT/v1/links/short/:idUpdate a short link
DELETE/v1/links/short/:idDelete a short link
GET/v1/links/short/:id/qrGet QR code for a short link
GET/v1/links/domainsList custom domains
POST/v1/links/domains/fallbackSet domain fallback URL
GET/v1/linksList all links (unified, with search/filter/sort)
GET/v1/links/:idGet a single link by ID (redirect or short link)

For detailed Links API documentation including request/response schemas and examples, see the Links API Reference.


POST /v1/track

Track an analytics event for your application.

Request

Headers:

HeaderRequiredDescription
x-api-keyYesYour API key
Content-TypeYesMust be application/json

Body:

{
  "event": "string (required)",
  "properties": "object (optional)",
  "timestamp": "ISO 8601 string (optional)"
}
FieldTypeRequiredDescription
eventstringYesEvent name (1-255 characters). Use descriptive names like page_view, button_click, purchase_completed.
propertiesobjectNoKey-value pairs with additional event data. Values can be strings, numbers, booleans, or nested objects.
timestampstringNoISO 8601 timestamp for when the event occurred. Defaults to server time if not provided.

Response

Success (202 Accepted):

{
  "success": true
}

The 202 Accepted status indicates the event was received and queued for asynchronous processing.

Examples

Track a page view:

curl -X POST https://api.compactsaas.com/v1/track \
  -H "x-api-key: pk_live_your_key_here" \
  -H "Content-Type: application/json" \
  -d '{
    "event": "page_view",
    "properties": {
      "page": "/pricing",
      "referrer": "https://google.com"
    }
  }'

Track a button click:

curl -X POST https://api.compactsaas.com/v1/track \
  -H "x-api-key: pk_live_your_key_here" \
  -H "Content-Type: application/json" \
  -d '{
    "event": "button_click",
    "properties": {
      "button_id": "signup_cta",
      "button_text": "Get Started"
    }
  }'

Track a purchase with timestamp:

curl -X POST https://api.compactsaas.com/v1/track \
  -H "x-api-key: pk_live_your_key_here" \
  -H "Content-Type: application/json" \
  -d '{
    "event": "purchase_completed",
    "properties": {
      "product_id": "prod_123",
      "amount": 99.99,
      "currency": "USD"
    },
    "timestamp": "2024-01-15T10:30:00Z"
  }'

Billing

Each call to /v1/track is counted as one API call for billing purposes. Usage is aggregated hourly and appears on your monthly Stripe invoice.

Tenant Isolation

Events are automatically associated with your team based on the API key used. You cannot specify a different team ID in the request body—tenant identification is handled securely by the API key authorizer.


GET /v1/health

Health check endpoint for monitoring and uptime checks.

Request

Headers: None required (no authentication)

Response

Success (200 OK):

{
  "status": "ok",
  "timestamp": "2024-01-15T10:30:00.000Z",
  "version": "v1"
}
FieldTypeDescription
statusstringAlways "ok" when healthy
timestampstringCurrent server timestamp (ISO 8601)
versionstringAPI version ("v1")

Example

curl https://api.compactsaas.com/v1/health

Response:

{
  "status": "ok",
  "timestamp": "2024-01-15T10:30:00.000Z",
  "version": "v1"
}

Use Cases

  • Uptime monitoring (e.g., Pingdom, UptimeRobot)
  • Load balancer health checks
  • Pre-flight checks before sending events

Links API

The Links API provides URL redirect management, short link generation, and custom domain configuration. All links endpoints are under the /v1/links/ prefix.

Key Features

  • Redirects — Route traffic from one domain/path to another with 301/302 redirects served at the edge (sub-millisecond)
  • Short Links — Generate compact URLs on the platform's short domain with auto-generated or custom codes
  • Click Analytics — Enable analyticsEnabled on any link to track clicks as pageviews in your analytics dashboard, billed via the advanced_analytics_pageviews meter
  • Custom Domains — Serve redirects from your own domain with managed TLS certificates

Quick Example

# Create a short link with analytics
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/campaign", "analyticsEnabled": true}'
{
  "link": {
    "id": "01KK6MCSFTTM0GPJB3XEBWJACY",
    "shortCode": "oTmGvkP",
    "shortUrl": "https://urlz.zip/oTmGvkP",
    "targetUrl": "https://example.com/campaign",
    "analyticsEnabled": true,
    "analyticsWebsiteId": "01KK6MD0A1B2C3D4E5F6G7H8J9",
    "hasClicks": true
  }
}
# Get a single short link
curl https://api.compactsaas.com/v1/links/short/01KK6MCSFTTM0GPJB3XEBWJACY \
  -H "x-api-key: pk_live_your_key_here"
{
  "link": {
    "id": "01KK6MCSFTTM0GPJB3XEBWJACY",
    "shortCode": "oTmGvkP",
    "shortUrl": "https://urlz.zip/oTmGvkP",
    "targetUrl": "https://example.com/campaign",
    "domain": "urlz.zip",
    "enabled": true,
    "analyticsEnabled": true,
    "analyticsWebsiteId": "01KK6MD0A1B2C3D4E5F6G7H8J9",
    "hasClicks": true,
    "createdAt": 1773056521115,
    "updatedAt": 1773056521115
  }
}
# Get click statistics (last 14 days)
curl "https://api.compactsaas.com/v1/links/short/01KK6MCSFTTM0GPJB3XEBWJACY/stats?days=14" \
  -H "x-api-key: pk_live_your_key_here"
{
  "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 }
  ]
}

For the complete Links API reference with all endpoints, request/response schemas, and examples, see the Links API Reference.

Unified Links

# List all links (both redirects and short links)
curl "https://api.compactsaas.com/v1/links?type=shortlink&search=example&sort=created&order=desc" \
  -H "x-api-key: pk_live_your_key_here"
// Response
{
  "links": [
    {
      "id": "01KK6MCSFTTM0GPJB3XEBWJACY",
      "type": "shortlink",
      "sourceUrl": "s.urlz.zip/abc123",
      "shortCode": "abc123",
      "shortUrl": "s.urlz.zip/abc123",
      "targetUrl": "https://example.com",
      "domain": "s.urlz.zip",
      "enabled": true,
      "analyticsEnabled": true,
      "analyticsWebsiteId": "01KKPHGQRZRG6PQGHPCG69GZDS",
      "hasClicks": true,
      "createdAt": "2026-03-15T10:00:00.000Z",
      "updatedAt": "2026-03-15T10:00:00.000Z"
    }
  ]
}
# Get a single link by ID (works for both redirects and short links)
curl https://api.compactsaas.com/v1/links/01KK6MCSFTTM0GPJB3XEBWJACY \
  -H "x-api-key: pk_live_your_key_here"
// Response
{
  "link": {
    "id": "01KK6MCSFTTM0GPJB3XEBWJACY",
    "type": "shortlink",
    "sourceUrl": "s.urlz.zip/abc123",
    "shortCode": "abc123",
    "targetUrl": "https://example.com",
    "enabled": true,
    "analyticsEnabled": true,
    "createdAt": "2026-03-15T10:00:00.000Z",
    "updatedAt": "2026-03-15T10:00:00.000Z"
  }
}

Bio Pages API

The Bio Pages API lets you create and manage link-in-bio pages programmatically. Each bio page gets a tracked short link, full analytics, and a public URL. All endpoints are under the /v1/bio/ prefix.

Key Features

  • Themed Pages — Customize colors, button styles, fonts, and social icons
  • Link Management — Add existing short links to your bio page with drag-to-reorder
  • Analytics — Every page view and link click tracked through the analytics pipeline
  • Social Sharing — OG meta tags served to social media crawlers for rich previews
  • Avatar Images — Upload profile images stored in S3 with presigned URLs

Quick Example

# Create a bio page
curl -X POST https://api.compactsaas.com/v1/bio \
  -H "x-api-key: pk_live_your_key_here" \
  -H "Content-Type: application/json" \
  -d '{"title": "My Links", "bio": "Developer & creator", "published": true}'

# Response
# {"bioPage": {"id": "01J...", "title": "My Links", "shortUrl": "https://staging.urlz.zip/abc123", ...}}

Endpoints

MethodPathDescription
POST/v1/bioCreate a bio page
GET/v1/bioList all bio pages
GET/v1/bio/:pageIdGet a bio page
PUT/v1/bio/:pageIdUpdate a bio page
DELETE/v1/bio/:pageIdDelete a bio page

Create/Update Fields

FieldTypeDescription
titlestringPage title (required on create, max 200 chars)
biostringBio text (max 2000 chars)
publishedbooleanWhether the page is publicly visible
linksarrayOrdered list of {shortLinkId, title, visible}
socialLinksarrayList of {platform, url} — platforms: twitter, instagram, tiktok, youtube, linkedin, github, facebook, website
themeobject{bgColor, textColor, buttonColor, buttonTextColor, buttonBorderRadius, buttonStyle, fontFamily}

Error Responses

All error responses follow a consistent format:

{
  "error": "Error Type",
  "message": "Human-readable description",
  "code": "MACHINE_READABLE_CODE"
}

Error Codes Reference

HTTP StatusError CodeDescriptionCommon Causes
400VALIDATION_ERRORInvalid request bodyMissing event field, invalid JSON, invalid timestamp format
401UNAUTHORIZEDAuthentication failedMissing API key, invalid API key, revoked API key
403ACCOUNT_DISABLEDAccount access deniedAccount disabled, suspended, or payment failed
404NOT_FOUNDEndpoint not foundInvalid URL path
429RATE_LIMIT_EXCEEDEDRate limit exceededToo many requests per second
500INTERNAL_ERRORServer errorUnexpected server-side error

Detailed Error Examples

400 Bad Request - Missing Event Name

{
  "error": "Validation error",
  "message": "Event name is required",
  "code": "VALIDATION_ERROR"
}

Cause: The event field is missing or empty in the request body.

Solution: Include a valid event name in your request:

{
  "event": "page_view",
  "properties": {}
}

400 Bad Request - Invalid Timestamp

{
  "error": "Validation error",
  "message": "Invalid datetime format for timestamp",
  "code": "VALIDATION_ERROR"
}

Cause: The timestamp field is not a valid ISO 8601 string.

Solution: Use ISO 8601 format: 2024-01-15T10:30:00Z

401 Unauthorized - Invalid API Key

{
  "error": "Unauthorized",
  "message": "Invalid or missing API key",
  "code": "UNAUTHORIZED"
}

Cause:

  • API key is missing from the x-api-key header
  • API key is invalid or malformed
  • API key has been revoked

Solution:

  1. Verify the x-api-key header is included
  2. Check that the key matches the format pk_live_... or pk_test_...
  3. Verify the key hasn't been revoked in the dashboard

403 Forbidden - Account Disabled

{
  "error": "Forbidden",
  "message": "Account is disabled. Please contact support.",
  "code": "ACCOUNT_DISABLED"
}

Cause:

  • Account has been disabled by an administrator
  • Subscription has been cancelled
  • Payment has failed

Solution:

  1. Check your account status in the dashboard
  2. Verify your payment method is up to date
  3. Contact support if the issue persists

429 Too Many Requests - Rate Limited

{
  "error": "Too Many Requests",
  "message": "Rate limit exceeded. Please retry after the specified time.",
  "code": "RATE_LIMIT_EXCEEDED"
}

Headers:

Retry-After: 60

Cause: You've exceeded the rate limit of 100 requests per second.

Solution:

  1. Wait for the duration specified in the Retry-After header
  2. Implement exponential backoff in your retry logic
  3. Consider batching events to reduce request frequency

500 Internal Server Error

{
  "error": "Internal Server Error",
  "message": "An unexpected error occurred",
  "code": "INTERNAL_ERROR"
}

Cause: An unexpected error occurred on the server.

Solution:

  1. Retry the request with exponential backoff
  2. Check the status page for incidents
  3. Contact support if the issue persists

Request/Response Schemas

TrackEventRequest

interface TrackEventRequest {
  // Required: Name of the event (1-255 characters)
  event: string;

  // Optional: Additional event properties
  properties?: Record<string, any>;

  // Optional: ISO 8601 timestamp (defaults to server time)
  timestamp?: string;
}

TrackEventResponse

interface TrackEventResponse {
  success: boolean;
}

HealthResponse

interface HealthResponse {
  status: "ok";
  timestamp: string;  // ISO 8601 format
  version: string;    // e.g., "v1"
}

ErrorResponse

interface ErrorResponse {
  error: string;      // Error type
  message: string;    // Human-readable description
  code: ErrorCode;    // Machine-readable code
}

type ErrorCode =
  | "VALIDATION_ERROR"
  | "UNAUTHORIZED"
  | "ACCOUNT_DISABLED"
  | "RATE_LIMIT_EXCEEDED"
  | "INTERNAL_ERROR"
  | "NOT_FOUND";

Billing

Pay-As-You-Go Model

CompactSaaS uses a simple pay-as-you-go billing model:

  • No monthly quotas - Use as much as you need
  • No tiers - Same rate for all customers
  • Transparent pricing - See current rates in your dashboard

How Billing Works

  1. Each API call to /v1/track is counted
  2. Usage is aggregated hourly
  3. Usage is reported to Stripe Billing Meters
  4. All API calls appear on your monthly Stripe invoice

Viewing Usage

  1. Log in to your CompactSaaS Dashboard
  2. Navigate to BillingUsage
  3. View current billing period usage and estimated cost

Billing vs Rate Limits

AspectRate LimitsBilling
PurposeDDoS protectionUsage tracking
Limit typeRequests per secondNone (pay-as-you-go)
Enforcement429 responseMonthly invoice
ConfigurableNoPricing in dashboard

Security

API Key Security

  • API keys are hashed (SHA-256) before storage
  • Full keys are shown only once at creation
  • Keys can be revoked immediately
  • Revoked keys are disabled in real-time

Tenant Isolation

  • Tenant identification comes from the API key, not request body
  • All data operations are scoped to your team
  • Cross-tenant access is prevented at the data layer

Transport Security

  • All API traffic uses HTTPS (TLS 1.2+)
  • HTTP requests are rejected

WAF Protection

  • AWS WAF protects against common attacks
  • IP-based rate limiting (10,000 requests per 5 minutes per IP)
  • AWS Managed Rules for common vulnerabilities

Best Practices

Event Naming

Use consistent, descriptive event names:

Good: page_view, button_click, purchase_completed, user_signup
Bad: event1, click, e, pv

Properties

Include relevant context in properties:

{
  "event": "purchase_completed",
  "properties": {
    "product_id": "prod_123",
    "product_name": "Pro Plan",
    "amount": 99.99,
    "currency": "USD",
    "payment_method": "card"
  }
}

Error Handling

Implement robust error handling:

async function trackEvent(event, properties) {
  try {
    const response = await fetch('https://api.compactsaas.com/v1/track', {
      method: 'POST',
      headers: {
        'x-api-key': API_KEY,
        'Content-Type': 'application/json',
      },
      body: JSON.stringify({ event, properties }),
    });

    if (response.status === 429) {
      const retryAfter = response.headers.get('Retry-After') || 60;
      // Wait and retry
    }

    if (!response.ok) {
      const error = await response.json();
      console.error(`API error: ${error.code} - ${error.message}`);
    }

    return response.json();
  } catch (error) {
    console.error('Network error:', error);
    // Queue for retry
  }
}

Retry Strategy

Use exponential backoff for retries:

async function trackWithRetry(event, properties, maxRetries = 3) {
  for (let attempt = 0; attempt < maxRetries; attempt++) {
    try {
      const response = await trackEvent(event, properties);
      return response;
    } catch (error) {
      if (attempt === maxRetries - 1) throw error;

      const delay = Math.pow(2, attempt) * 1000; // 1s, 2s, 4s
      await new Promise(resolve => setTimeout(resolve, delay));
    }
  }
}

Related Documentation


Support


Changelog

v1.3.0

  • Bio Pages: POST /v1/bio — create a link-in-bio page
  • Bio Pages: GET /v1/bio — list bio pages
  • Bio Pages: GET /v1/bio/:pageId — get bio page details
  • Bio Pages: PUT /v1/bio/:pageId — update bio page
  • Bio Pages: DELETE /v1/bio/:pageId — delete bio page
  • QR Codes: Added API Gateway routes for /v1/qr/* endpoints (previously missing)

v1.2.0

  • Unified links: GET /v1/links — list all links with search, filter, sort
  • Unified links: GET /v1/links/:id — get any link by ID (redirect or short link)

v1.1.0

  • Links API: Redirects CRUD (/v1/links/redirects)
  • Links API: Short Links CRUD (/v1/links/shorten, /v1/links/short)
  • Links API: Custom Domains (/v1/links/domains)
  • Click analytics: analyticsEnabled field on redirects and short links
  • Analytics dashboard: Websites, Links, and Redirects tabs

v1.0.0

  • Initial release
  • POST /v1/track - Analytics event tracking
  • GET /v1/health - Health check endpoint
  • API key authentication
  • Pay-as-you-go billing via Stripe
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.