{
  "openapi": "3.1.0",
  "info": {
    "title": "Klickr API",
    "version": "1.0.0",
    "summary": "Create short links, ephemeral ticket links, and read public platform stats.",
    "description": "Welcome to the Klickr developer reference. Klickr turns one short link into infinite\ndestinations: platform-aware redirects, rich social previews, QR codes, click analytics,\nand SequrMark link verification.\n\nThis API lets external systems create links programmatically. Everything else\n(campaigns, analytics, user management, billing) is managed in the\n[Klickr dashboard](https://klickr.io/dashboard).\n\n## Base URLs\n\n| Purpose | Base URL |\n|---|---|\n| API endpoints | `https://api.klickr.io` |\n| Short link resolution | `https://klickr.io` |\n\nAll endpoints live under `/v1`. Breaking changes will ship under a new version prefix,\nnever by changing the behaviour of an existing path.\n\nOlder integrations may still call the functions directly at\n`https://us-central1-klickr-io.cloudfunctions.net/createKlickApi`,\n`.../createTicketLinkApi` and `.../getPlatformStats`. Those URLs keep working but are\ntied to a deployment region and are not guaranteed to be stable. Use `api.klickr.io`.\n\n## Authentication\n\nWrite endpoints are authenticated with an API key sent in the `x-api-key` header.\n\n* Keys are created in the dashboard under **Businesses → API Keys**. The raw key is\n  shown **once** at creation time and only a SHA-256 hash is stored, so copy it\n  immediately.\n* Keys look like `klk_` followed by 64 hex characters.\n* Every key is scoped to a single business. Links you create are owned by that\n  business and appear in its dashboard.\n* Keys can be revoked at any time from the same screen. A revoked key returns\n  `401 Unauthorized` on the next request.\n* Treat keys as secrets: call the API from your backend, never from a browser or\n  mobile app you ship to users.\n\nPublic endpoints (platform stats and link resolution) need no credentials.\n\n## Quick start\n\n```bash\ncurl -X POST \"https://api.klickr.io/v1/klicks\" \\\n  -H \"Content-Type: application/json\" \\\n  -H \"x-api-key: klk_your_api_key\" \\\n  -d '{\n    \"name\": \"Spring launch\",\n    \"destinationUrl\": \"https://example.com/spring\",\n    \"slug\": \"spring-2026\"\n  }'\n```\n\n```json\n{\n  \"id\": \"spring-2026\",\n  \"shortUrl\": \"https://klickr.io/spring-2026\",\n  \"destinationUrl\": \"https://example.com/spring\",\n  \"name\": \"Spring launch\",\n  \"createdAt\": \"2026-09-07T09:30:00.000Z\"\n}\n```\n\n## Conventions\n\n* Request and response bodies are JSON (`Content-Type: application/json`).\n* Timestamps are ISO 8601 strings in UTC.\n* Every error response is a JSON object with a single human-readable `error` string.\n* Write endpoints accept `POST` only. Any other method returns `405`.\n* All API endpoints send permissive CORS headers (`Access-Control-Allow-Origin: *`)\n  and answer `OPTIONS` preflight requests with `204`.\n\n## Choosing between Klicks and Ticket Links\n\n| | Klick | Ticket Link |\n|---|---|---|\n| Endpoint | `POST /v1/klicks` | `POST /v1/ticket-links` |\n| Lifetime | Permanent until archived | Expires at `expiryDate`, then deleted |\n| Dashboard | Yes: analytics, QR code, editing | No (counter on the business only) |\n| Click analytics | Yes | No |\n| Social previews, platform targeting | Yes | No |\n| SequrMark verification | Yes | No |\n| Batch create | No | Yes, up to 499 per request |\n| Typical use | Marketing links, QR codes, app downloads | One-shot SMS ticket URLs, OTP-style links |\n\n## Limits\n\n* `createTicketLinkApi` accepts at most **499** items per request.\n* The redirect host rate-limits clients that request more than 5 unknown short codes\n  per minute from one IP (`429`).\n* There is no published request quota on the API endpoints. Please keep sustained\n  traffic reasonable and contact Klickr before running large migrations.\n\n## What is not in this reference\n\nThe Klickr dashboard and partner applications also use Firebase callable functions\n(user invitations, click recording, SequrMark vetting and token management). Those\nrequire a Firebase ID token from the Klickr app and are not part of the public API.\n",
    "contact": {
      "name": "Klickr",
      "url": "https://klickr.io"
    },
    "license": {
      "name": "Proprietary",
      "identifier": "LicenseRef-Klickr-Proprietary"
    }
  },
  "servers": [
    {
      "url": "https://api.klickr.io",
      "description": "Production API"
    }
  ],
  "security": [
    {
      "ApiKeyAuth": []
    }
  ],
  "tags": [
    {
      "name": "Klicks",
      "description": "Permanent short links managed in the Klickr dashboard. A Klick carries a display\nname, an optional custom slug, platform-specific destinations, Open Graph social\npreview metadata, and click analytics.\n"
    },
    {
      "name": "Ticket Links",
      "description": "Ephemeral short links for transactional messages such as SMS tickets. They resolve\nwith a fast `302` redirect, carry no analytics or social preview, and are deleted\nautomatically once their expiry passes.\n"
    },
    {
      "name": "Platform",
      "description": "Public, unauthenticated read endpoints."
    },
    {
      "name": "Resolution",
      "description": "How `klickr.io/{shortCode}` behaves when a person or a crawler opens a link. This is\nserved from `https://klickr.io`, not from the API base URL.\n"
    }
  ],
  "paths": {
    "/v1/klicks": {
      "post": {
        "tags": [
          "Klicks"
        ],
        "operationId": "createKlick",
        "summary": "Create a Klick",
        "description": "Creates a permanent short link owned by the business the API key belongs to.\n\n* Omit `slug` to receive a random, URL-safe short code.\n* Slugs are unique case-insensitively across all Klicks and Ticket Links.\n  `Summer-Sale` and `summer-sale` are the same link.\n* `campaignId` must reference a campaign that belongs to the same business.\n* Set `isConfirmation: true` for transactional links (order or ticket confirmations).\n  They are listed under the **Confirmations** tab in the dashboard rather than with\n  marketing links, but otherwise behave like any Klick.\n\nThe link is live immediately at `https://klickr.io/{id}`.\n",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateKlickRequest"
              },
              "examples": {
                "minimal": {
                  "summary": "Minimal (random short code)",
                  "value": {
                    "name": "My campaign link",
                    "destinationUrl": "https://example.com/landing-page"
                  }
                },
                "customSlug": {
                  "summary": "Custom slug",
                  "value": {
                    "name": "Summer sale 2026",
                    "destinationUrl": "https://example.com/summer-sale",
                    "slug": "summer-sale-2026"
                  }
                },
                "fullOptions": {
                  "summary": "Platform targeting and social preview",
                  "value": {
                    "name": "App download link",
                    "destinationUrl": "https://example.com/download",
                    "slug": "get-app",
                    "campaignId": "3f9Kq2LmPzRt",
                    "platformDestinations": {
                      "ios": "https://apps.apple.com/app/example/id123456",
                      "android": "https://play.google.com/store/apps/details?id=com.example",
                      "other": "https://example.com/download"
                    },
                    "socialPreview": {
                      "title": "Download our app",
                      "description": "Available on iOS and Android.",
                      "imageUrl": "https://example.com/og/app.png"
                    }
                  }
                },
                "confirmation": {
                  "summary": "Confirmation link",
                  "value": {
                    "name": "Ticket #TK-48291",
                    "destinationUrl": "https://tickets.example.com/view/TK-48291",
                    "isConfirmation": true
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Klick created.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/KlickCreated"
                },
                "examples": {
                  "randomCode": {
                    "value": {
                      "id": "aB3xKz9mNwPq",
                      "shortUrl": "https://klickr.io/aB3xKz9mNwPq",
                      "destinationUrl": "https://example.com/landing-page",
                      "name": "My campaign link",
                      "createdAt": "2026-09-07T09:30:00.000Z"
                    }
                  },
                  "customSlug": {
                    "value": {
                      "id": "summer-sale-2026",
                      "shortUrl": "https://klickr.io/summer-sale-2026",
                      "destinationUrl": "https://example.com/summer-sale",
                      "name": "Summer sale 2026",
                      "createdAt": "2026-09-07T09:30:00.000Z"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Validation failed.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "missingFields": {
                    "value": {
                      "error": "Missing required fields: destinationUrl, name"
                    }
                  },
                  "badUrl": {
                    "value": {
                      "error": "Invalid destinationUrl — must be a valid http(s) URL"
                    }
                  },
                  "badName": {
                    "value": {
                      "error": "name must be a non-empty string (max 200 chars)"
                    }
                  },
                  "badSlug": {
                    "value": {
                      "error": "Invalid slug — must be 3-64 characters, alphanumeric, hyphens, or underscores"
                    }
                  },
                  "unknownPlatform": {
                    "value": {
                      "error": "Unknown platform: windows"
                    }
                  },
                  "badPlatformUrl": {
                    "value": {
                      "error": "Invalid URL for platform ios"
                    }
                  },
                  "badCampaign": {
                    "value": {
                      "error": "Invalid campaignId — not found or not owned by this business"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "405": {
            "$ref": "#/components/responses/MethodNotAllowed"
          },
          "409": {
            "description": "The slug is already taken by another Klick or Ticket Link.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "This slug is already taken"
                }
              }
            }
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/v1/ticket-links": {
      "post": {
        "tags": [
          "Ticket Links"
        ],
        "operationId": "createTicketLinks",
        "summary": "Create one or many Ticket Links",
        "description": "Creates ephemeral short links. Send a single object to create one link, or an\narray (max 499) to create many in one atomic write. If any item fails validation\nor collides with an existing slug, nothing is created and the error names the\noffending item by its zero-based index.\n\nBehaviour of a Ticket Link:\n\n* `slug` is required and is lower-cased. The returned `shortUrl` has no scheme\n  (`klickr.io/abc123`) to save characters in SMS messages. Prefix `https://` if\n  your channel needs it.\n* `expiryDate` must be in the future. After that instant the link resolves to\n  `404`, and the record is deleted by a background TTL job (up to 24 hours later).\n* Resolution is a plain `302` to `destinationUrl`. No click analytics, social\n  preview, platform targeting, or verification is applied.\n* Ticket Links do not appear in the dashboard. The business record keeps a\n  lifetime `ticketLinkCount`.\n",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "oneOf": [
                  {
                    "$ref": "#/components/schemas/CreateTicketLinkRequest"
                  },
                  {
                    "type": "array",
                    "title": "Batch",
                    "description": "Up to 499 ticket links, created atomically.",
                    "minItems": 1,
                    "maxItems": 499,
                    "items": {
                      "$ref": "#/components/schemas/CreateTicketLinkRequest"
                    }
                  }
                ]
              },
              "examples": {
                "single": {
                  "summary": "Single link",
                  "value": {
                    "slug": "TK48291",
                    "destinationUrl": "https://tickets.example.com/view/TK-48291",
                    "expiryDate": "2026-12-31T23:59:59Z"
                  }
                },
                "batch": {
                  "summary": "Batch of links",
                  "value": [
                    {
                      "slug": "TK48291",
                      "destinationUrl": "https://tickets.example.com/view/TK-48291",
                      "expiryDate": "2026-12-31T23:59:59Z"
                    },
                    {
                      "slug": "TK48292",
                      "destinationUrl": "https://tickets.example.com/view/TK-48292",
                      "expiryDate": "2026-12-31T23:59:59Z"
                    }
                  ]
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Created. The shape depends on the request: a single object returns one\n`TicketLink`, an array returns a `TicketLinkBatch`.\n",
            "content": {
              "application/json": {
                "schema": {
                  "oneOf": [
                    {
                      "$ref": "#/components/schemas/TicketLink"
                    },
                    {
                      "$ref": "#/components/schemas/TicketLinkBatch"
                    }
                  ]
                },
                "examples": {
                  "single": {
                    "summary": "Single link",
                    "value": {
                      "slug": "tk48291",
                      "shortUrl": "klickr.io/tk48291",
                      "destinationUrl": "https://tickets.example.com/view/TK-48291",
                      "expiresAt": "2026-12-31T23:59:59.000Z"
                    }
                  },
                  "batch": {
                    "summary": "Batch of links",
                    "value": {
                      "created": 2,
                      "links": [
                        {
                          "slug": "tk48291",
                          "shortUrl": "klickr.io/tk48291",
                          "destinationUrl": "https://tickets.example.com/view/TK-48291",
                          "expiresAt": "2026-12-31T23:59:59.000Z"
                        },
                        {
                          "slug": "tk48292",
                          "shortUrl": "klickr.io/tk48292",
                          "destinationUrl": "https://tickets.example.com/view/TK-48292",
                          "expiresAt": "2026-12-31T23:59:59.000Z"
                        }
                      ]
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Validation failed. Item errors are prefixed with the zero-based index of the\nfailing item, for example `Item 3: invalid destinationUrl`.\n",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "empty": {
                    "value": {
                      "error": "No items provided"
                    }
                  },
                  "tooMany": {
                    "value": {
                      "error": "Maximum 499 items per request"
                    }
                  },
                  "missingFields": {
                    "value": {
                      "error": "Item 0: missing required fields (destinationUrl, slug, expiryDate)"
                    }
                  },
                  "badUrl": {
                    "value": {
                      "error": "Item 0: invalid destinationUrl"
                    }
                  },
                  "badSlug": {
                    "value": {
                      "error": "Item 0: invalid slug — must be 3-64 chars, alphanumeric, hyphens, or underscores"
                    }
                  },
                  "badDate": {
                    "value": {
                      "error": "Item 0: invalid expiryDate (must be ISO 8601)"
                    }
                  },
                  "pastDate": {
                    "value": {
                      "error": "Item 0: expiryDate must be in the future"
                    }
                  },
                  "duplicateInRequest": {
                    "value": {
                      "error": "Duplicate slug in request: TK48291"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "405": {
            "$ref": "#/components/responses/MethodNotAllowed"
          },
          "409": {
            "description": "A slug collides with an existing Klick or Ticket Link. Nothing was created.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "Slug already taken: tk48291"
                }
              }
            }
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/v1/stats": {
      "get": {
        "tags": [
          "Platform"
        ],
        "operationId": "getPlatformStats",
        "summary": "Get platform statistics",
        "security": [],
        "description": "Aggregate, platform-wide counters as shown on the Klickr landing page. The\nresponse is cached at the CDN for five minutes (`Cache-Control: public, max-age=300`)\nand served from a periodically refreshed snapshot, so `updatedAt` may lag real time.\n",
        "responses": {
          "200": {
            "description": "Current platform statistics.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string"
                },
                "example": "public, max-age=300"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PlatformStats"
                },
                "example": {
                  "totalLinks": 34,
                  "totalClicks": 30948,
                  "totalBusinesses": 8,
                  "updatedAt": "2026-03-14T18:51:07.703Z"
                }
              }
            }
          },
          "500": {
            "description": "Stats could not be computed.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "Failed to get platform stats"
                }
              }
            }
          }
        }
      }
    },
    "/{shortCode}": {
      "servers": [
        {
          "url": "https://klickr.io",
          "description": "Short link host"
        }
      ],
      "get": {
        "tags": [
          "Resolution"
        ],
        "operationId": "resolveShortCode",
        "summary": "Resolve a short link",
        "security": [],
        "description": "Opens a Klick or Ticket Link. Matching is case-insensitive. This endpoint is\ndesigned for browsers and crawlers rather than API clients, so most outcomes are\nHTML pages. Use it to understand what your users will experience.\n\n**Klicks**\n\n| Situation | Status | Body |\n|---|---|---|\n| Browser opens an active link | `200` | HTML page that immediately redirects to the destination with JavaScript |\n| Social crawler or bot opens an active link | `200` | HTML with Open Graph and Twitter Card meta tags, no redirect |\n| Link is SequrMark-verified | `200` | Verified interstitial page showing the trust score before continuing |\n| Link failed verification or its token was revoked | `200` | Warning page; the visitor may still choose to continue |\n| Link is archived | `410` | HTML that redirects to `https://klickr.io/removed` |\n| Unknown short code | `404` | Not-found page |\n\nPlatform targeting is applied from the `User-Agent`: iOS devices go to\n`platformDestinations.ios`, Android to `platformDestinations.android`, everything\nelse to `platformDestinations.other`, falling back to `destinationUrl`. Clicks from\nnon-bot user agents are counted in analytics.\n\n**Ticket Links**\n\nAn unexpired Ticket Link answers with a plain `302` and a `Location` header. An\nexpired one answers `404`.\n\n**Abuse protection**\n\nKnown scanner IP ranges receive `403`. Short codes that look like vulnerability\nprobes (for example `wp-login.php` or `.env`) receive `404` without a lookup. An\nIP that requests more than 5 unknown short codes within one minute receives `429`.\n",
        "parameters": [
          {
            "name": "shortCode",
            "in": "path",
            "required": true,
            "description": "The Klick slug or Ticket Link slug. Case-insensitive.",
            "schema": {
              "type": "string",
              "pattern": "^[a-zA-Z0-9_-]{3,64}$",
              "example": "summer-sale-2026"
            }
          },
          {
            "name": "User-Agent",
            "in": "header",
            "required": false,
            "description": "Drives platform targeting and bot detection.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Active Klick. The HTML body is one of: a JavaScript redirect (browsers), an\nOpen Graph preview (crawlers), a verified interstitial, or a warning page.\n",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string"
                },
                "example": "private, max-age=0, no-cache, must-revalidate"
              }
            },
            "content": {
              "text/html": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "302": {
            "description": "Unexpired Ticket Link. Follow `Location`.",
            "headers": {
              "Location": {
                "description": "The Ticket Link destination URL.",
                "schema": {
                  "type": "string",
                  "format": "uri"
                }
              }
            }
          },
          "403": {
            "description": "Request came from a blocked IP.",
            "content": {
              "text/plain": {
                "schema": {
                  "type": "string",
                  "example": "Forbidden"
                }
              }
            }
          },
          "404": {
            "description": "Unknown or expired short code, or a blocked scanner-style path.",
            "content": {
              "text/html": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "410": {
            "description": "Archived Klick. The HTML body redirects to `https://klickr.io/removed`.",
            "content": {
              "text/html": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Too many unknown short codes requested from this IP in the last minute.",
            "content": {
              "text/plain": {
                "schema": {
                  "type": "string",
                  "example": "Too many requests"
                }
              }
            }
          },
          "500": {
            "description": "Unexpected error while resolving the link.",
            "content": {
              "text/plain": {
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "ApiKeyAuth": {
        "type": "apiKey",
        "in": "header",
        "name": "x-api-key",
        "description": "Business-scoped API key created in the Klickr dashboard (**Businesses → API Keys**).\nFormat: `klk_` followed by 64 hexadecimal characters.\n"
      }
    },
    "responses": {
      "Unauthorized": {
        "description": "The `x-api-key` header is missing, malformed, revoked, or unknown.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            },
            "examples": {
              "missing": {
                "value": {
                  "error": "Missing or invalid API key"
                }
              },
              "unknown": {
                "value": {
                  "error": "Invalid API key"
                }
              }
            }
          }
        }
      },
      "MethodNotAllowed": {
        "description": "Only `POST` (and `OPTIONS` preflight) is accepted.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            },
            "example": {
              "error": "Method not allowed"
            }
          }
        }
      },
      "InternalError": {
        "description": "Unexpected server error. Safe to retry with backoff.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            },
            "example": {
              "error": "Internal error"
            }
          }
        }
      }
    },
    "schemas": {
      "Error": {
        "type": "object",
        "required": [
          "error"
        ],
        "properties": {
          "error": {
            "type": "string",
            "description": "Human-readable description of what went wrong."
          }
        },
        "example": {
          "error": "Invalid API key"
        }
      },
      "Slug": {
        "type": "string",
        "description": "Custom short code. 3 to 64 characters from `A-Z a-z 0-9 _ -`. Uniqueness is\nchecked case-insensitively across Klicks and Ticket Links.\n",
        "pattern": "^[a-zA-Z0-9_-]{3,64}$",
        "minLength": 3,
        "maxLength": 64,
        "examples": [
          "summer-sale-2026",
          "TK48291"
        ]
      },
      "HttpUrl": {
        "type": "string",
        "format": "uri",
        "description": "Absolute `http://` or `https://` URL.",
        "examples": [
          "https://example.com/landing-page"
        ]
      },
      "PlatformDestinations": {
        "type": "object",
        "description": "Optional per-platform destinations chosen from the visitor's `User-Agent`. Any\nplatform left out falls back to `destinationUrl`. Only the three keys below are\naccepted; any other key is rejected with `400`.\n",
        "properties": {
          "ios": {
            "allOf": [
              {
                "$ref": "#/components/schemas/HttpUrl"
              }
            ],
            "description": "Destination for iPhone, iPad, and iPod visitors."
          },
          "android": {
            "allOf": [
              {
                "$ref": "#/components/schemas/HttpUrl"
              }
            ],
            "description": "Destination for Android visitors."
          },
          "other": {
            "allOf": [
              {
                "$ref": "#/components/schemas/HttpUrl"
              }
            ],
            "description": "Destination for every other visitor, including desktop browsers."
          }
        },
        "additionalProperties": false
      },
      "SocialPreview": {
        "type": "object",
        "description": "Open Graph and Twitter Card metadata served to social crawlers. Missing fields fall\nback to the Klick name, a default description, and the Klickr default image.\n",
        "properties": {
          "title": {
            "type": "string",
            "description": "`og:title`. Defaults to the Klick name."
          },
          "description": {
            "type": "string",
            "description": "`og:description`."
          },
          "imageUrl": {
            "allOf": [
              {
                "$ref": "#/components/schemas/HttpUrl"
              }
            ],
            "description": "`og:image`. A 1200×630 image works best across networks."
          }
        }
      },
      "CreateKlickRequest": {
        "type": "object",
        "required": [
          "name",
          "destinationUrl"
        ],
        "properties": {
          "name": {
            "type": "string",
            "description": "Display name shown in the dashboard. Trimmed; 1 to 200 characters.",
            "minLength": 1,
            "maxLength": 200,
            "examples": [
              "Summer sale 2026"
            ]
          },
          "destinationUrl": {
            "allOf": [
              {
                "$ref": "#/components/schemas/HttpUrl"
              }
            ],
            "description": "Default destination when no platform-specific URL applies."
          },
          "slug": {
            "allOf": [
              {
                "$ref": "#/components/schemas/Slug"
              }
            ],
            "description": "Custom short code. Omit for a random, URL-safe code."
          },
          "campaignId": {
            "type": "string",
            "description": "ID of a campaign belonging to the same business as the API key.",
            "examples": [
              "3f9Kq2LmPzRt"
            ]
          },
          "platformDestinations": {
            "$ref": "#/components/schemas/PlatformDestinations"
          },
          "socialPreview": {
            "$ref": "#/components/schemas/SocialPreview"
          },
          "isConfirmation": {
            "type": "boolean",
            "default": false,
            "description": "Mark as a transactional confirmation link. Listed under the **Confirmations**\ntab in the dashboard instead of with marketing links.\n"
          }
        }
      },
      "KlickCreated": {
        "type": "object",
        "required": [
          "id",
          "shortUrl",
          "destinationUrl",
          "name",
          "createdAt"
        ],
        "properties": {
          "id": {
            "type": "string",
            "description": "The Klick ID. Equals `slug` when one was supplied, otherwise a random code.",
            "examples": [
              "summer-sale-2026",
              "aB3xKz9mNwPq"
            ]
          },
          "shortUrl": {
            "type": "string",
            "format": "uri",
            "description": "The public short link.",
            "examples": [
              "https://klickr.io/summer-sale-2026"
            ]
          },
          "destinationUrl": {
            "$ref": "#/components/schemas/HttpUrl"
          },
          "name": {
            "type": "string",
            "description": "The trimmed display name."
          },
          "createdAt": {
            "type": "string",
            "format": "date-time",
            "description": "Creation time in UTC."
          }
        }
      },
      "CreateTicketLinkRequest": {
        "type": "object",
        "title": "TicketLinkInput",
        "required": [
          "slug",
          "destinationUrl",
          "expiryDate"
        ],
        "properties": {
          "slug": {
            "allOf": [
              {
                "$ref": "#/components/schemas/Slug"
              }
            ],
            "description": "Required. Stored and returned in lower case."
          },
          "destinationUrl": {
            "allOf": [
              {
                "$ref": "#/components/schemas/HttpUrl"
              }
            ],
            "description": "Where the link redirects."
          },
          "expiryDate": {
            "type": "string",
            "format": "date-time",
            "description": "ISO 8601 timestamp after which the link stops resolving. Must be in the future.",
            "examples": [
              "2026-12-31T23:59:59Z"
            ]
          }
        }
      },
      "TicketLink": {
        "type": "object",
        "required": [
          "slug",
          "shortUrl",
          "destinationUrl",
          "expiresAt"
        ],
        "properties": {
          "slug": {
            "type": "string",
            "description": "The lower-cased slug, which is also the document ID.",
            "examples": [
              "tk48291"
            ]
          },
          "shortUrl": {
            "type": "string",
            "description": "Public short link **without** a scheme, ready to drop into an SMS.",
            "examples": [
              "klickr.io/tk48291"
            ]
          },
          "destinationUrl": {
            "$ref": "#/components/schemas/HttpUrl"
          },
          "expiresAt": {
            "type": "string",
            "format": "date-time",
            "description": "Normalised expiry in UTC."
          }
        }
      },
      "TicketLinkBatch": {
        "type": "object",
        "required": [
          "created",
          "links"
        ],
        "properties": {
          "created": {
            "type": "integer",
            "description": "Number of links created. Equals the request array length.",
            "examples": [
              2
            ]
          },
          "links": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/TicketLink"
            }
          }
        }
      },
      "PlatformStats": {
        "type": "object",
        "required": [
          "totalLinks",
          "totalClicks",
          "totalBusinesses",
          "updatedAt"
        ],
        "properties": {
          "totalLinks": {
            "type": "integer",
            "description": "Total Klicks ever created on the platform."
          },
          "totalClicks": {
            "type": "integer",
            "description": "Sum of click counts across all Klicks."
          },
          "totalBusinesses": {
            "type": "integer",
            "description": "Number of businesses on the platform."
          },
          "updatedAt": {
            "type": "string",
            "format": "date-time",
            "description": "When the snapshot was last recomputed."
          }
        }
      }
    }
  }
}