Skip to main content

AI-native links

AI-readable links, by default.

Every CLYK short link and bio page answers in two dialects. Humans get a redirect. AI agents get structured JSON — same URL, zero configuration. No SDK. No model strings. Just content negotiation done right.

Content negotiation on every short link

The same /i/{code} URL serves a 301 redirect to browsers and a structured JSON body to AI agents. We inspect the Accept header, the user-agent, and an optional ?format=json override.

Human: HEAD request (gets the redirect)
curl -sI https://clyk.app/i/abc123
# HTTP/2 301
# location: https://example.com/real-url
# x-clyk-link-meta: https://clyk.app/i/abc123?format=json
# link: <https://clyk.app/i/abc123?format=json>; rel="alternate"; type="application/json"
AI agent: Accept: application/json (gets metadata)
curl -sH "Accept: application/json" https://clyk.app/i/abc123
# {
#   "short_url": "https://clyk.app/i/abc123",
#   "short_code": "abc123",
#   "destination": "https://example.com/real-url",
#   "title": "Launch announcement",
#   "clicks": { "total": 1240, "human": 1188, "bot": 52 },
#   "mcp": { "server": "https://clyk.app/api/mcp", "tools": ["get_link", "get_link_stats", ...] }
# }

Password-protected links surface only the short code and a password_protected: trueflag. Expired links surface the expiration state without the destination. Anonymous links omit the owner block. Guardrails are enforced in the edge handler — there's no opt-in needed.

Every HTML redirect response also carries two discovery headers so crawlers that don't content-negotiate can still find the JSON endpoint: X-CLYK-Link-Meta and an RFC-5988 Link: ...; rel="alternate".

Bio pages mirror to JSON

Public bio pages at /{username} have a parallel JSON endpoint at /{username}/meta. CLYK short links embedded in a bio are auto-resolved so AI agents see destinations and click counts without a second round-trip.

Bio page JSON mirror
curl -s https://clyk.app/alice/meta
# {
#   "username": "alice",
#   "owner": { "display_name": "Alice", "bio": "...", "avatar_url": "..." },
#   "theme": { "mode": "dark", "accent_color": "#22d3c4", ... },
#   "links": [
#     {
#       "title": "My launch",
#       "url": "https://clyk.app/i/abc123",
#       "short_code": "abc123",
#       "destination": "https://example.com/real-url",
#       "clyk_link_meta": "https://clyk.app/i/abc123?format=json"
#     }
#   ],
#   "mcp": { "server": "https://clyk.app/api/mcp", "tools": [...] }
# }

The HTML page also embeds Schema.org JSON-LD (a Person + a WebPage + an ItemList of every bio link) in the document head, so crawling agents that don't content-negotiate still see structured data when they parse the markup.

Site-wide discovery

Standard files and API documents tell any AI agent where to find us, how to behave, and how paid data is purchased.

Discovery surfaces
# Plain-text operator manual for AI agents
curl https://clyk.app/llms.txt

# MCP discovery
curl https://clyk.app/.well-known/mcp.json

# A2A agent card
curl https://clyk.app/.well-known/agent-card.json

# Agent-commerce paid data API
curl https://clyk.app/api/agent/v1/openapi.json
curl https://clyk.app/api/agent/v1/quote

# OAuth 2.0 metadata (RFC 8414 + 9728)
curl https://clyk.app/.well-known/oauth-authorization-server
curl https://clyk.app/.well-known/oauth-protected-resource

# Legacy plugin manifest (points at OpenAPI)
curl https://clyk.app/.well-known/ai-plugin.json
  • /llms.txt — plain-text operator manual. Who we are, how to interact, privacy rules, rate limits, contact.
  • /.well-known/mcp.json — MCP discovery. Points at the server endpoint, manifest, and auth docs.
  • /.well-known/mcp/server-card.json — SEP-1649 canonical MCP server card with serverInfo, capabilities, and transport.
  • /.well-known/api-catalog — RFC 9727 API catalog (application/linkset+json) listing REST and MCP surfaces with their service-desc / service-doc URLs.
  • /.well-known/agent-skills/index.json — Cloudflare Agent Skills Discovery v0.2.0 index. Each skill carries a SHA-256 over its SKILL.md body.
  • /.well-known/agent-card.json — A2A Agent Card listing supported interfaces (MCP + REST), capabilities, payments, and skills.
  • /api/agent/v1/openapi.json — paid agent-commerce OpenAPI spec. These endpoints return HTTP 402 MPP challenges for Link-backed Stripe SPT payments.
  • /api/agent/v1/quote — current machine-readable prices for paid link and destination data.
  • /.well-known/oauth-authorization-server — RFC 8414 OAuth 2.0 authorization server metadata. Points at /oauth/authorize, /oauth/token, and /oauth/register.
  • /.well-known/oauth-protected-resource — RFC 9728 protected resource metadata for /api/v1.
  • /.well-known/openid-configuration — OIDC-compat discovery document (mirrors the 8414 payload so OIDC-aware clients find us).
  • /.well-known/http-message-signatures-directory — Web Bot Auth directory. Public JWKS for verifying signed outbound webhooks.
  • /.well-known/ai-plugin.json — legacy ChatGPT-plugin manifest for older agents.
  • /robots.txt — carries a Cloudflare Content-Signal directive: ai-train=yes, search=yes, ai-input=yes. CLYK wants LLMs and agents to know we exist.
  • WebMCP — the homepage registers an in-page shorten_url tool via navigator.modelContext.provideContext() for browser-resident agents.
  • Markdown negotiation — send Accept: text/markdown to any of /, /pricing, /vs-bitly, /vs-linktree, /developers, /developers/api, /developers/mcp, /developers/ai-nativeand we'll reply with a pre-generated markdown mirror.

What to set in your AI client

For tool-use workflows, point your MCP-aware client at our server. For pure read-only crawl scenarios, just set Accept: application/json.

MCP client config · or ad-hoc curl
# Any MCP-aware client (Claude Desktop, Claude Code, Cursor):
{
  "mcpServers": {
    "clyk": {
      "url": "https://clyk.app/api/mcp",
      "headers": { "Authorization": "Bearer YOUR_CLYK_API_KEY" }
    }
  }
}

# For ad-hoc scripts, just ask for JSON:
curl -H "Accept: application/json" https://clyk.app/i/abc123

Ship AI-aware, without ceremony.

No SDK. No keys for a model we don't host. Just a URL that answers in the dialect the caller asks for.