# frwrd.to > Short links and bio pages, agent first. A workspace is a domain; its > credential is a key shown once at creation; ownership is proven with a DNS > TXT record. No accounts, no passwords. ## Reading a page - https://frwrd.to/@ HTML. is a workspace uid (w-...), a claimed handle, or the workspace's domain. - https://frwrd.to/@/ A further page of the workspace. - https://frwrd.to/@.md The same page as Markdown. Prefer this one: it is what the author wrote, with no markup to strip. Every HTML page advertises it via . /@/.md for a further page. - https://frwrd.to/@/de/ A page in another language than the workspace's default sits under that language's two-letter code; /@/de is its root. HTML pages carry hreflang links to their translations. - https://frwrd.to/@/llms.txt The workspace's own index: every page with its .md address, language and translations. - https://frwrd.to/@/sitemap.xml The same as a sitemap, with hreflang pairs. - https://frwrd.to/@.qr The page's QR code (SVG); .qr for a further page. A scan counts as a view on channel qr. ## Writing The REST API at https://frwrd.to's api host (api.) is the contract; how to use it, with examples, is at https://frwrd.to/@frwrd.to/help-api (as Markdown: https://frwrd.to/@frwrd.to/help-api.md), and for agents over MCP at https://frwrd.to/@frwrd.to/help-mcp.md. - POST /v1/workspaces {"domain":"acme.com"} Create a workspace. Returns the key (once) and a DNS TXT record to publish. - POST /v1/workspace/verify Check the record; lifts the quota. - PUT /v1/pages/ The whole page as text/markdown (Content-Type: text/markdown). "-" is the root page. If-Match: the version you read. Every http(s) link in the document becomes a short link with the page's UTM defaults; stats come free. - GET /v1/pages/ Accept: text/markdown gives the document back byte for byte, with an ETag. - GET /v1/pages//stats Views, and clicks per link. - POST /v1/links {"long_url": "..."} A short link on its own. - GET /v1/links//qr.svg Its QR code (scans count separately). All write endpoints take `Authorization: Bearer `. Errors are {"error":{"code","message"}}; branch on code. ## MCP The same capabilities as MCP tools, over Streamable HTTP at the api host's /mcp with the workspace key as the bearer: get_workspace, verify_workspace, claim_handle, set_utm, list_domains, add_domain, remove_domain, create_link, list_links, get_link, update_link, archive_link, get_link_stats, get_qr, list_pages, get_page, write_page, delete_page, get_page_stats, list_page_versions; resource frwrd://pages/{path}. Tool errors start with the same codes as the REST errors. A page is Markdown with YAML front matter: --- title: Acme description: Tools for people who ship. avatar: https://cdn.acme.com/logo.png theme: { accent: "#ff5a1f", background: light } lang: en utm: { source: frwrd, medium: bio } --- # Acme - [Our product](https://acme.com/product) - [The blog](https://acme.com/blog) A link alone in a list item or paragraph renders as a card; an inline link stays inline. Raw HTML is dropped. ## Notes - Workspace creation is rate-limited per client; a 429 means wait. - An unverified workspace expires after 31 days and may hold 50 links. Every page says in its footer whether its domain is verified. - Markdown renderings are excluded from search indexing via robots.txt; they stay fetchable.