REST API
Base URL: https://linkmag.net/v1. The machine-readable contract is the OpenAPI document at https://linkmag.net/v1/openapi.json; GET /v1 lists the same endpoints.
Formats
Every endpoint answers in JSON. Send Accept: text/markdown for a readable summary that states what happened and the next call, or Accept: text/plain for key=value lines that a shell can parse without a JSON tool.
Authentication
Send an API key as Authorization: Bearer <key>. Keys start with lm_.
To get one without a browser session, use the device flow:
curl -s -X POST https://linkmag.net/v1/keys/requests \
-H 'Content-Type: application/json' -d '{"client_name": "My agent"}'The response holds user_code, approve_url, request_id and device_code. The user opens the link, signs in and approves the code. Poll the claim endpoint every interval seconds:
curl -s -X POST https://linkmag.net/v1/keys/requests/REQUEST_ID/claim \
-H 'Content-Type: application/json' -d '{"device_code": "DEVICE_CODE"}'It answers 202 {"status":"pending"} until approval, then 200 with api_key exactly once. Requests expire after 15 minutes. Signed-in users can also create and revoke keys on the API keys page.
Endpoints
| Method | Path | Key | Purpose |
|---|---|---|---|
| POST | /v1/keys/requests | no | Start a key request |
| POST | /v1/keys/requests/{requestId}/claim | no | Claim the key after approval |
| GET | /v1/validate?url= | no | Audit any public page's tags |
| GET | /v1/sites | yes | List sites |
| POST | /v1/sites | yes | Create a site |
| GET | /v1/sites/{siteId} | yes | Site, domains, usage |
| DELETE | /v1/sites/{siteId} | yes | Delete a site |
| POST | /v1/sites/{siteId}/domains | yes | Register a hostname |
| POST | /v1/sites/{siteId}/domains/{hostname}/verify | yes | Verify by DNS or meta tag |
| DELETE | /v1/sites/{siteId}/domains/{hostname} | yes | Remove a hostname |
| PATCH | /v1/sites/{siteId}/template | yes | Layout, colors, logo, caption, badge |
| GET | /v1/sites/{siteId}/usage | yes | Renders this month |
| GET | /v1/sites/{siteId}/snippet?framework= | yes | Install code for a framework |
| GET | /v1/sites/{siteId}/preview?path= | yes | Card URL for a path |
| POST | /v1/sites/{siteId}/purge | yes | Drop cached cards (Pro, Business) |
| GET | /v1/og/{siteId} | no | The card image itself |
Errors
Errors carry a machine code, a message and a fix:
{"error": {"code": "unauthorized", "message": "This call needs an API key.", "fix": "Request one with POST /v1/keys/requests, …"}}Codes: unauthorized (401), forbidden and plan_required (403), not_found (404), invalid_request (400), conflict and limit_reached (409), server_error (500). The card endpoint answers 429 when the monthly render allowance is used up.
Agents can request any page on this site as markdown by sending Accept: text/markdown.