Skip to main content

Developer guide

Changelog

View as Markdown

Everything that has changed in this API, newest first. Check here before you ship — new capabilities show up in this list before you would notice them anywhere else.

Versioning

The version field of this document (currently 1.14.0) moves with the API and follows semantic versioning:

BumpMeans
MAJORA breaking change — a field or endpoint removed, a response shape changed, a previously optional field made required.
MINORA new endpoint, a new optional field, a new accepted value. Existing integrations keep working untouched.
PATCHDocumentation corrections and bug fixes with no contract change.

Nothing is removed without warning. A field on its way out is first marked deprecated in this reference and listed under Deprecated below, and it keeps working for at least one MINOR cycle. Deprecated fields are still accepted, so an integration that has not migrated yet will not start failing.

Two habits keep you safe against MINOR releases: ignore response fields you do not recognise rather than validating strictly against a fixed shape, and never assume a list field is a merge — several (geo_rules, Shield's rules) replace the whole array.


2026-10-04 - 1.14.0

Added - stored integration reads and MCP guidance Eight GET routes under /api/v2/integrations expose connections, metrics, tracking links, account summaries, statements and fan health. Explicit integrations.read and current project/account rights apply. The Integrations and MCP sections explain common revenue readings, freshness, paging, scheduling limits and the read-only review workflow. This documents the implemented contract; deployment and account eligibility must be verified.


2026-08-06 — 1.13.0

Added — folders are fully manageable from the API POST /api/v1/folders creates one, and GET, PATCH and DELETE /api/v1/folders/{folder_id} read, rename and delete it. Only the folder listing existed before, so an integration could see folders but never make one. Permissions: folders.create, folders.read, folders.edit, folders.delete — these already existed on your API keys and finally have endpoints behind them.

Added — file a link into a folder when you create or update it PUT /api/v1/links and PATCH /api/v1/links/{link_id} accept folder_id (single folder, null to clear) and folders (the full array — a link can sit in several folders at once; sending it replaces the whole list). Links created through the API no longer land outside every folder waiting to be dragged into place by hand. Sending both spellings at once, or a folder id from another project, is a 400. See the new Folders section above.

Added — the folders of a link are returned link.folders (an array of folder ids) is now on GET /api/v1/links, GET /api/v1/links/{link_id}, and echoed by both write verbs. It is always present — [] for a link outside every folder — and is exactly the shape you send back on a PATCH. GET /api/v1/links/{link_id} additionally returns a sibling folders array with the names resolved.

Added — ?folder_id= on the link list GET /api/v1/links?folder_id=... returns only the links inside one folder.


2026-08-03 — 1.12.0

Added — Media previews on every asset GET /api/v1/assets and GET /api/v1/assets/{file_id} now return thumbnail_url (320px), preview_url (1024px), media_kind (image/video/audio/document) and is_image. Render a gallery straight from those URLs instead of hand-building CDN transformations. The two preview URLs are null for anything that is not an image — video and PDF have no server-rendered still frame, so branch on media_kind.

Added — sort on the asset list ?sort=newest|oldest|largest|smallest|name (default newest). Anything else is a 400.

Fixed — the asset list is finally paginable total used to repeat the size of the page you just received; it now counts every asset matching your filters. limit, offset, the new count (this page) and has_more come back with it. If you were treating total as "assets on this page", switch to count.

Fixed — file_id is back in the list, and reaches every file The list endpoint never returned file_id, so there was no way to go from a listing to GET /api/v1/assets/{file_id}. It is returned again — and both endpoints now resolve dashboard-uploaded files too (their UUID is stored under provider_file_id), which previously 404'd on the detail route.

Fixed — ?file_type= no longer hides files with a generic MIME type Files stored as application/octet-stream are now matched on their filename extension as well, so ?file_type=video returns the whole set.

Changed — user_id removed from the asset detail response An internal identifier that the list endpoint never exposed. No other field changed.


2026-08-03 — 1.11.1

Documentation — what an API-created link inherits A new section, Links created through the API, answers the question directly: a link created with PUT /api/v1/links is the same object as one created in the dashboard, with the same landing-page, Shield, template, Geo Filter and Privacy capabilities, and it stays editable in the dashboard afterwards. The one difference is ownership — an API key is a project credential, so the link belongs to the project rather than to a team member. That matters only for dashboard permissions on teams using per-member roles, and is spelled out there. No API change.


2026-08-03 — 1.11.0

Fixed — GET /api/v1/trending-links now actually exists This endpoint has been documented for a while but was never wired up: calling it returned a 404 HTML page. It is live now, behind the statistics.read_project permission, and returns exactly the payload described below. The project is resolved from your API key — project_id is optional, and sending another project's id is a 403 rather than a cross-project read.


2026-08-03 — 1.10.0

Added — Link Privacy (privacy.links) Make a link private from the API, the same switch as Privacy in the dashboard: {"privacy": {"links": true}} on PUT /api/v1/links and PATCH /api/v1/links/{id}. The destinations the link renders are then served through a short redirect on your own domain (https://<your-domain>/go/<token>), so the real URL never appears in the HTML a crawler reads. The call that flips the switch provisions those redirects — there is nothing else to enable. Send {"links": false} to go back to normal.

The flag is returned by every link read — GET /api/v1/links, GET /api/v1/links/{id} and the PUT /api/v1/links response — always as privacy: { links: <boolean> }, false on a link that was never made private. See the Link Privacy section.

2026-08-02 — 1.9.0

Added — every template family is now selectable on a link A link has four template slots, and until now only the landing one could be set through the API. All four are now accepted on PUT /api/v1/links and PATCH /api/v1/links/{id}, and returned together under templates by GET /api/v1/links/{id}: cs_template (landing), cs_1-step (first-step gate), cs_3dots_template (direct 3-dots overlay) and cs_3dots_click_template (click 3-dots overlay). Send null on any of them to detach. See Templates — the three families.

Added — ?kind= on the Templates endpoints GET /api/v1/templates and GET /api/v1/templates/{template_id} take kind=landing|first_step|three_dots, so the ids for the new slots are discoverable. Defaults to landing, so existing calls are unchanged. Both responses now echo the kind they served. GET /api/v1/templates also takes ?summary=true for a trimmed listing — recommended, since the default response returns full template documents and a v2 template embeds a whole page.

Changed — template ids are checked against your project A template id that does not belong to the authenticated project is now rejected with 400 naming the field, on every slot. It was previously accepted for cs_template, which let a link be pointed at another project's template. If you send ids you did not get from GET /api/v1/templates, check them before upgrading.

Fixed — PATCH /api/v1/links/{id} accepts cs_template It previously silently ignored it; the only way to attach a landing template to an existing link was PUT|PATCH /api/v1/links/{id}/dynamic-overrides, which still works and remains the right call when you set the template and its dynamic_informations / dynamic_links together.

Fixed — Templates response shapes documented correctly GET /api/v1/templates returns { templates, kind, project } and GET /api/v1/templates/{template_id} returns { template, kind, project }. This reference previously described a { success, data } envelope neither of them has ever returned. No API change — the documentation was wrong.


2026-08-01 — 1.8.0

Added — Geo Filters (geo_rules) Per-visitor overrides on a link: block a country, redirect a region to a localized destination, or serve a different landing page per browser language. Settable on PUT /api/v1/links and PATCH /api/v1/links/{id}, returned in full by GET /api/v1/links/{id}, and summarised as geo_rules_count on GET /api/v1/links. See the Geo Filters section for the model and examples.

Added — Shield (/api/v1/links/{link_id}/shield) Traffic filtering and cloaking as a first-class resource: read, replace (PUT), patch, and disable (DELETE) a link's Shield configuration, plus GET /api/v1/shield for the condition vocabulary, GET /api/v1/shield/presets for the built-in presets, and GET /api/v1/shield/bots for the crawler registry. See the Shield section.

Deprecated — geolocation_enabled, geolocation_redirects These two fields on PATCH /api/v1/links/{id} were never read by the serve layer: setting them did nothing, and links "configured" with them were not geo-targeted at all. They are still accepted so existing callers do not break, but they are now discarded rather than stored. Migrate to geo_rules — a { countries, url } entry becomes a rule with t: "d_l".

Fixed — link detail response documented correctly GET /api/v1/links/{id} returns { link, project }. It was previously documented as { success, data }, which never matched the actual response. The endpoint itself is unchanged; only the reference was wrong.

2026-07-24

Added — Landing Pages (v2) Read and write Page Builder v2 pages on links and templates (/api/v1/links/{link_id}/landing, /api/v1/templates/{template_id}/landing), with version history, per-link dynamic-overrides, and the /api/v1/landing-engine contract and example endpoints.

2026-03-31

Added — Visit logs GET /api/v1/logs, /api/v1/links/{link_id}/logs and /api/v1/folders/{folder_id}/logs — cursor-paginated visit history with masked IPs and each visit's clicks merged in. See the API Logs section.

2026-02-19

Added — Social networks & trending links Connected-account analytics, post metrics and history under /api/v1/social-networks, plus GET /api/v1/trending-links.

2025-10-25

Added — Folders /api/v1/folders and folder-scoped statistics.

2025-10-17

Initial public API — links, templates, assets and statistics.


Keeping this list current (internal note). This changelog lives in the info.description of static/openapi.yaml and nowhere else — there is no second copy to drift out of sync. When you change the API: add a dated entry at the top of the list under the right label (Added / Changed / Deprecated / Removed / Fixed), say what a consumer must do rather than what the code now does, and bump info.version plus the number quoted under Versioning above.

Browse API endpoints