Links API endpoints to create, list, retrieve, update, and delete deep links, including destinations, fallbacks, and UTM parameters.
Create a Link
POST/links
Create a link
Request Body
Field
Type
Description
destination_url*
string
slug
string
Custom slug. Auto-generated if omitted.
name
string
The link's name in the dashboard. Shows the slug if omitted.
domain
string
Domain to serve this link from. A link with an app defaults to the app's default_link_domain. A web-only link (no app) defaults to aplnk.to, and an existing link with no app keeps aplnk.to. A legacy app (legacy_apex_enabled) can use aplnk.to, its subdomain (link_domain) or a live custom domain. A new app can use its subdomain or a live custom domain, never aplnk.to (422 INVALID_DOMAIN). An explicit domain is never replaced. The slug test is reserved on an app subdomain. An app's previous subdomain (previous_link_domain) never takes new links.
ios_url
string
ios_fallback_url
string
android_url
string
android_fallback_url
string
og_title
string
og_description
string
og_image_url
string
tags
string[]
expires_at
string
Must be in the future.
password
string
app_id
string
utm_source
string
Added to the redirect URL as utm_source when no higher source supplies one. Order for utm_source: an injected utm_source in "always" mode wins; otherwise the visitor's own utm_source when parameters.forwarding passes it, then a utm_source already in the destination URL, then an injected utm_source in "default" mode (this field is then not used), then this field. Applies to http and https URLs only; not to apps.apple.com, itunes.apple.com, play.google.com, apps.microsoft.com or custom-scheme URLs.
utm_medium
string
Added to the redirect URL as utm_medium when no higher source supplies one. Order for utm_medium: an injected utm_medium in "always" mode wins; otherwise the visitor's own utm_medium when parameters.forwarding passes it, then a utm_medium already in the destination URL, then an injected utm_medium in "default" mode (this field is then not used), then this field. Applies to http and https URLs only; not to apps.apple.com, itunes.apple.com, play.google.com, apps.microsoft.com or custom-scheme URLs.
utm_campaign
string
Added to the redirect URL as utm_campaign when no higher source supplies one. Order for utm_campaign: an injected utm_campaign in "always" mode wins; otherwise the visitor's own utm_campaign when parameters.forwarding passes it, then a utm_campaign already in the destination URL, then an injected utm_campaign in "default" mode (this field is then not used), then this field. Applies to http and https URLs only; not to apps.apple.com, itunes.apple.com, play.google.com, apps.microsoft.com or custom-scheme URLs.
match_window_hours
integer
Deferred deep link attribution match window in hours.
parameters
object | null
Per-link query-parameter rules. `injected` params are appended to the destination URL; `forwarding` controls which incoming params pass through. Org-level defaults are inherited and merged with link-level config (link wins on key conflict). Precedence: link > org. Send `null` (or omit) to clear/inherit the org defaults.
Responses
201Link created
Field
Type
Description
id
string
short_url
string
e.g. https://aplnk.to/abc123
slug
string
e.g. abc123
name
string | null
The link's own name in the dashboard. Null shows the slug.e.g. Summer sale
domain
string
e.g. aplnk.to
destination_url
string
ios_url
string | null
ios_fallback_url
string | null
android_url
string | null
android_fallback_url
string | null
og_title
string | null
og_description
string | null
og_image_url
string | null
app_id
string | null
utm_source
string | null
Added to the redirect URL as utm_source when no higher source supplies one. Order for utm_source: an injected utm_source in "always" mode wins; otherwise the visitor's own utm_source when parameters.forwarding passes it, then a utm_source already in the destination URL, then an injected utm_source in "default" mode (this field is then not used), then this field. Applies to http and https URLs only; not to apps.apple.com, itunes.apple.com, play.google.com, apps.microsoft.com or custom-scheme URLs.
utm_medium
string | null
Added to the redirect URL as utm_medium when no higher source supplies one. Order for utm_medium: an injected utm_medium in "always" mode wins; otherwise the visitor's own utm_medium when parameters.forwarding passes it, then a utm_medium already in the destination URL, then an injected utm_medium in "default" mode (this field is then not used), then this field. Applies to http and https URLs only; not to apps.apple.com, itunes.apple.com, play.google.com, apps.microsoft.com or custom-scheme URLs.
utm_campaign
string | null
Added to the redirect URL as utm_campaign when no higher source supplies one. Order for utm_campaign: an injected utm_campaign in "always" mode wins; otherwise the visitor's own utm_campaign when parameters.forwarding passes it, then a utm_campaign already in the destination URL, then an injected utm_campaign in "default" mode (this field is then not used), then this field. Applies to http and https URLs only; not to apps.apple.com, itunes.apple.com, play.google.com, apps.microsoft.com or custom-scheme URLs.
match_window_hours
integer | null
expires_at
string | null
is_active
boolean
tags
string[]
parameters
object | null
Per-link query-parameter rules. `injected` params are appended to the destination URL; `forwarding` controls which incoming params pass through. Org-level defaults are inherited and merged with link-level config (link wins on key conflict). Precedence: link > org. Send `null` (or omit) to clear/inherit the org defaults.
created_at
string
updated_at
string
redirected_from
object[]
Old URLs of this link that redirect to it with a permanent 301, oldest first. Present only on GET /v1/links/{id} (and the get_link MCP tool), not on list, update, activate or deactivate responses.
400Validation error
Field
Type
Description
error*
object
401Unauthorized
Field
Type
Description
error*
object
403Forbidden. APP_REQUIRED: the organization has no registered app yet. Create an app with POST /apps, then create the link. LINK_LIMIT_EXCEEDED: the plan's link limit has been reached.
Field
Type
Description
error*
object
409SLUG_TAKEN: the slug is already taken on that domain, it is the old address of a moved link, or it is held for a link of the same app that still waits to move there (details.slug and details.domain, plus details.held_by with the old domain and slug for a held address). A slug must be unique only on the domain you pick. DEFAULT_DOMAIN_UNAVAILABLE: the request names no domain and the app's saved default is a custom domain that is no longer live (details.allowed_link_domains lists what to choose instead). APP_LINK_STATE_CHANGED: the app's address or default changed while the link was being created; read the app and retry.
Field
Type
Description
error*
object
422INVALID_DOMAIN: the domain is not allowed for this link. A new app cannot use aplnk.to. Use the app's subdomain or a live custom domain.
Field
Type
Description
error*
object
429Rate limit exceeded
Field
Type
Description
error*
object
List Links
GET/links
List links
Parameters
Name
Type
In
Description
limit
integer
query
offset
integer
query
tag
string
query
is_active
"true" | "false"
query
search
string
query
Responses
200List of links
Field
Type
Description
data
object[]
pagination
object
401Unauthorized
Field
Type
Description
error*
object
403Forbidden
Field
Type
Description
error*
object
Get a Link
GET/links/{id}
Get a link
Parameters
Name
Type
In
Description
id*
string
path
Responses
200Link details
Field
Type
Description
id
string
short_url
string
e.g. https://aplnk.to/abc123
slug
string
e.g. abc123
name
string | null
The link's own name in the dashboard. Null shows the slug.e.g. Summer sale
domain
string
e.g. aplnk.to
destination_url
string
ios_url
string | null
ios_fallback_url
string | null
android_url
string | null
android_fallback_url
string | null
og_title
string | null
og_description
string | null
og_image_url
string | null
app_id
string | null
utm_source
string | null
Added to the redirect URL as utm_source when no higher source supplies one. Order for utm_source: an injected utm_source in "always" mode wins; otherwise the visitor's own utm_source when parameters.forwarding passes it, then a utm_source already in the destination URL, then an injected utm_source in "default" mode (this field is then not used), then this field. Applies to http and https URLs only; not to apps.apple.com, itunes.apple.com, play.google.com, apps.microsoft.com or custom-scheme URLs.
utm_medium
string | null
Added to the redirect URL as utm_medium when no higher source supplies one. Order for utm_medium: an injected utm_medium in "always" mode wins; otherwise the visitor's own utm_medium when parameters.forwarding passes it, then a utm_medium already in the destination URL, then an injected utm_medium in "default" mode (this field is then not used), then this field. Applies to http and https URLs only; not to apps.apple.com, itunes.apple.com, play.google.com, apps.microsoft.com or custom-scheme URLs.
utm_campaign
string | null
Added to the redirect URL as utm_campaign when no higher source supplies one. Order for utm_campaign: an injected utm_campaign in "always" mode wins; otherwise the visitor's own utm_campaign when parameters.forwarding passes it, then a utm_campaign already in the destination URL, then an injected utm_campaign in "default" mode (this field is then not used), then this field. Applies to http and https URLs only; not to apps.apple.com, itunes.apple.com, play.google.com, apps.microsoft.com or custom-scheme URLs.
match_window_hours
integer | null
expires_at
string | null
is_active
boolean
tags
string[]
parameters
object | null
Per-link query-parameter rules. `injected` params are appended to the destination URL; `forwarding` controls which incoming params pass through. Org-level defaults are inherited and merged with link-level config (link wins on key conflict). Precedence: link > org. Send `null` (or omit) to clear/inherit the org defaults.
created_at
string
updated_at
string
redirected_from
object[]
Old URLs of this link that redirect to it with a permanent 301, oldest first. Present only on GET /v1/links/{id} (and the get_link MCP tool), not on list, update, activate or deactivate responses.
401Unauthorized
Field
Type
Description
error*
object
403Forbidden
Field
Type
Description
error*
object
404Not found
Field
Type
Description
error*
object
Update a Link
PATCH/links/{id}
Update a link
Parameters
Name
Type
In
Description
id*
string
path
Request Body
Field
Type
Description
destination_url
string
name
string | null
Rename the link. Send null to show the slug again.
ios_url
string | null
ios_fallback_url
string | null
android_url
string | null
android_fallback_url
string | null
og_title
string | null
og_description
string | null
og_image_url
string | null
tags
array | null
expires_at
string | null
password
string | null
app_id
string | null
utm_source
string | null
Added to the redirect URL as utm_source when no higher source supplies one. Order for utm_source: an injected utm_source in "always" mode wins; otherwise the visitor's own utm_source when parameters.forwarding passes it, then a utm_source already in the destination URL, then an injected utm_source in "default" mode (this field is then not used), then this field. Applies to http and https URLs only; not to apps.apple.com, itunes.apple.com, play.google.com, apps.microsoft.com or custom-scheme URLs.
utm_medium
string | null
Added to the redirect URL as utm_medium when no higher source supplies one. Order for utm_medium: an injected utm_medium in "always" mode wins; otherwise the visitor's own utm_medium when parameters.forwarding passes it, then a utm_medium already in the destination URL, then an injected utm_medium in "default" mode (this field is then not used), then this field. Applies to http and https URLs only; not to apps.apple.com, itunes.apple.com, play.google.com, apps.microsoft.com or custom-scheme URLs.
utm_campaign
string | null
Added to the redirect URL as utm_campaign when no higher source supplies one. Order for utm_campaign: an injected utm_campaign in "always" mode wins; otherwise the visitor's own utm_campaign when parameters.forwarding passes it, then a utm_campaign already in the destination URL, then an injected utm_campaign in "default" mode (this field is then not used), then this field. Applies to http and https URLs only; not to apps.apple.com, itunes.apple.com, play.google.com, apps.microsoft.com or custom-scheme URLs.
match_window_hours
integer | null
parameters
object | null
Per-link query-parameter rules. `injected` params are appended to the destination URL; `forwarding` controls which incoming params pass through. Org-level defaults are inherited and merged with link-level config (link wins on key conflict). Precedence: link > org. Send `null` (or omit) to clear/inherit the org defaults.
Responses
200Updated link
Field
Type
Description
id
string
short_url
string
e.g. https://aplnk.to/abc123
slug
string
e.g. abc123
name
string | null
The link's own name in the dashboard. Null shows the slug.e.g. Summer sale
domain
string
e.g. aplnk.to
destination_url
string
ios_url
string | null
ios_fallback_url
string | null
android_url
string | null
android_fallback_url
string | null
og_title
string | null
og_description
string | null
og_image_url
string | null
app_id
string | null
utm_source
string | null
Added to the redirect URL as utm_source when no higher source supplies one. Order for utm_source: an injected utm_source in "always" mode wins; otherwise the visitor's own utm_source when parameters.forwarding passes it, then a utm_source already in the destination URL, then an injected utm_source in "default" mode (this field is then not used), then this field. Applies to http and https URLs only; not to apps.apple.com, itunes.apple.com, play.google.com, apps.microsoft.com or custom-scheme URLs.
utm_medium
string | null
Added to the redirect URL as utm_medium when no higher source supplies one. Order for utm_medium: an injected utm_medium in "always" mode wins; otherwise the visitor's own utm_medium when parameters.forwarding passes it, then a utm_medium already in the destination URL, then an injected utm_medium in "default" mode (this field is then not used), then this field. Applies to http and https URLs only; not to apps.apple.com, itunes.apple.com, play.google.com, apps.microsoft.com or custom-scheme URLs.
utm_campaign
string | null
Added to the redirect URL as utm_campaign when no higher source supplies one. Order for utm_campaign: an injected utm_campaign in "always" mode wins; otherwise the visitor's own utm_campaign when parameters.forwarding passes it, then a utm_campaign already in the destination URL, then an injected utm_campaign in "default" mode (this field is then not used), then this field. Applies to http and https URLs only; not to apps.apple.com, itunes.apple.com, play.google.com, apps.microsoft.com or custom-scheme URLs.
match_window_hours
integer | null
expires_at
string | null
is_active
boolean
tags
string[]
parameters
object | null
Per-link query-parameter rules. `injected` params are appended to the destination URL; `forwarding` controls which incoming params pass through. Org-level defaults are inherited and merged with link-level config (link wins on key conflict). Precedence: link > org. Send `null` (or omit) to clear/inherit the org defaults.
created_at
string
updated_at
string
redirected_from
object[]
Old URLs of this link that redirect to it with a permanent 301, oldest first. Present only on GET /v1/links/{id} (and the get_link MCP tool), not on list, update, activate or deactivate responses.
400Validation error
Field
Type
Description
error*
object
401Unauthorized
Field
Type
Description
error*
object
403Forbidden
Field
Type
Description
error*
object
404Not found
Field
Type
Description
error*
object
422INVALID_DOMAIN: the link's domain is not one the new app_id uses, for example aplnk.to for a new app. A link's domain never changes, so create a new link for that app.
Field
Type
Description
error*
object
UTM Fields
utm_source, utm_medium and utm_campaign on a link add those query parameters to the URL a visitor is redirected to, including for links created before you set them. The same fields on the MCP create_link and update_link tools behave the same way.
A field applies to the URL the redirect sends the visitor to when that URL is an http or https URL. This covers the web destination and any http or https iOS or Android URL you set. It does not apply to pages on apps.apple.com, itunes.apple.com, play.google.com or apps.microsoft.com, or to custom-scheme deep links such as myapp://. Each field sets only its own key.
For one key, up to four sources can supply a value. The one that wins depends on the mode of an injected parameter for that key (in the link's parameters.injected or the organization's injected parameters):
An injected parameter in always mode wins over everything, including the visitor's own value.
Otherwise, the first of these that has a value wins:
The visitor's own value, when parameters.forwarding passes that key. The default forwarding rule passes five keys: utm_source, utm_medium, utm_campaign, utm_term and utm_content. Other keys, such as utm_id, are not forwarded by default.
A value already in the destination URL.
An injected parameter in default mode. When one exists for the key, the link field is not used for that key.
The link field.
So when the visitor, the destination URL, a default injected parameter and the link field all supply utm_source, the visitor's value is the one sent.
A key is never added twice. An empty or blank field adds nothing. Clearing a field (null on update) stops the tag on the next redirect. Clicks to a web destination record the UTM values the visitor was sent, read from the final URL, so an applied link field appears in analytics. App store and app scheme destinations keep the values from the tap.
Delete a Link
DELETE/links/{id}
Delete a link
Permanently deletes the link. This is not reversible: it also removes the link's click history and frees the slug for reuse. To pause a link instead while keeping its data, send a PATCH with `is_active` set to `false`.
Parameters
Name
Type
In
Description
id*
string
path
Responses
200Deleted link
Field
Type
Description
id
string
short_url
string
e.g. https://aplnk.to/abc123
slug
string
e.g. abc123
name
string | null
The link's own name in the dashboard. Null shows the slug.e.g. Summer sale
domain
string
e.g. aplnk.to
destination_url
string
ios_url
string | null
ios_fallback_url
string | null
android_url
string | null
android_fallback_url
string | null
og_title
string | null
og_description
string | null
og_image_url
string | null
app_id
string | null
utm_source
string | null
Added to the redirect URL as utm_source when no higher source supplies one. Order for utm_source: an injected utm_source in "always" mode wins; otherwise the visitor's own utm_source when parameters.forwarding passes it, then a utm_source already in the destination URL, then an injected utm_source in "default" mode (this field is then not used), then this field. Applies to http and https URLs only; not to apps.apple.com, itunes.apple.com, play.google.com, apps.microsoft.com or custom-scheme URLs.
utm_medium
string | null
Added to the redirect URL as utm_medium when no higher source supplies one. Order for utm_medium: an injected utm_medium in "always" mode wins; otherwise the visitor's own utm_medium when parameters.forwarding passes it, then a utm_medium already in the destination URL, then an injected utm_medium in "default" mode (this field is then not used), then this field. Applies to http and https URLs only; not to apps.apple.com, itunes.apple.com, play.google.com, apps.microsoft.com or custom-scheme URLs.
utm_campaign
string | null
Added to the redirect URL as utm_campaign when no higher source supplies one. Order for utm_campaign: an injected utm_campaign in "always" mode wins; otherwise the visitor's own utm_campaign when parameters.forwarding passes it, then a utm_campaign already in the destination URL, then an injected utm_campaign in "default" mode (this field is then not used), then this field. Applies to http and https URLs only; not to apps.apple.com, itunes.apple.com, play.google.com, apps.microsoft.com or custom-scheme URLs.
match_window_hours
integer | null
expires_at
string | null
is_active
boolean
tags
string[]
parameters
object | null
Per-link query-parameter rules. `injected` params are appended to the destination URL; `forwarding` controls which incoming params pass through. Org-level defaults are inherited and merged with link-level config (link wins on key conflict). Precedence: link > org. Send `null` (or omit) to clear/inherit the org defaults.
created_at
string
updated_at
string
redirected_from
object[]
Old URLs of this link that redirect to it with a permanent 301, oldest first. Present only on GET /v1/links/{id} (and the get_link MCP tool), not on list, update, activate or deactivate responses.
401Unauthorized
Field
Type
Description
error*
object
403Forbidden
Field
Type
Description
error*
object
404Not found
Field
Type
Description
error*
object
Move Choice
If an app's links later move to its subdomain, a link whose slug is taken on the target stays where it is. Choose a new slug (used if the link moves, and its old URL then redirects to it) or keep the link where it is. Owners and admins can set the choice for any link, members for their own. DELETE clears the choice.
PUT/links/{id}/move-choice
Choose how a link moves
For a link that cannot move with its slug: move it with a new slug (the old URL redirects to it), or keep it where it is. Owners and admins may set it for any link, members for their own. Needs the links:write scope.
Parameters
Name
Type
In
Description
id*
string
path
Responses
200The saved choice
Field
Type
Description
link_id
string
choice
"keep" | "new_slug"
new_slug
string | null
400Invalid link ID or body. SLUG_UNCHANGED when new_slug equals the link's current slug.
Field
Type
Description
error*
object
401Unauthorized
Field
Type
Description
error*
object
403Forbidden. A member can only change their own links.
Field
Type
Description
error*
object
404Not found
Field
Type
Description
error*
object
409SLUG_TAKEN when new_slug is held by a link or by an old URL on the target subdomain, or is the slug another link on the previous subdomain would use there, whether it chose it or keeps its own (details.slug and details.domain). LINK_MOVE_NOT_PENDING when the link does not use an app's previous subdomain.
Field
Type
Description
error*
object
DELETE/links/{id}/move-choice
Clear a link's move choice
Removes the choice, so the link moves with its slug when it can. Needs the links:write scope.
Parameters
Name
Type
In
Description
id*
string
path
Responses
204Cleared400Invalid link ID
Field
Type
Description
error*
object
401Unauthorized
Field
Type
Description
error*
object
403Forbidden. A member can only change their own links.
Field
Type
Description
error*
object
404Not found
Field
Type
Description
error*
object
409LINK_MOVE_NOT_PENDING when the link does not use an app's previous subdomain.
Field
Type
Description
error*
object
A link that has moved returns redirected_from on GET /v1/links/{id}: the old URLs that redirect to it, with the date each began. The field is not on the list, update, activate or deactivate responses.
Resolve a Link
GET/links/resolve/{slug}
Resolve a link by slug
Looks up a link by its slug and optional domain. Returns the link's deep link configuration for SDK use. A resolve that returns link data to the WarpLink SDK on a device records one click with the source `app_open`, so an in-app open appears in analytics and counts toward your plan's click allowance. Nothing else records a click: not a refusal, not a known bot, and not a server script or CI job calling this endpoint with a standard API key, which still receives the link data. `destination_url` and the platform URLs are normalized exactly the way the redirect path normalizes them, so a bare origin comes back with its trailing slash, and `custom_params` includes the query parameters already on the stored destination. A resolve that carries the same `X-WarpLink-Tap-Id` as an earlier one records one click, not two, so a client may safely retry a request whose response it never received. A slug that is the old address of a moved link resolves to the moved link: the response carries the link's current domain and slug, and the old address keeps working for as long as the link exists.
Parameters
Name
Type
In
Description
slug*
string
path
domain
string
query
Domain to resolve the slug against. Defaults to aplnk.to.
params
string
query
The tapped URL's raw query string, without the leading question mark. Applied to the returned destination and platform URLs the same way the redirect path applies it.
X-WarpLink-Tap-Id
string
header
A UUID identifying one tap. The WarpLink SDKs mint one per tap and send the same value on every bounded retry of that tap, so a request whose response was lost does not record a second click. Used as the click's id when it is a valid UUID; an absent or malformed value is ignored and an id is generated instead.
Responses
200Resolved link
Field
Type
Description
id
string
slug
string
domain
string
destination_url
string
ios_url
string | null
ios_fallback_url
string | null
android_url
string | null
android_fallback_url
string | null
custom_params
object
created_at
string
400Validation error
Field
Type
Description
error*
object
401Unauthorized
Field
Type
Description
error*
object
403The link is password protected (`PASSWORD_REQUIRED`). No destination or platform URLs are returned. Open the short URL in a browser to enter the password.
Field
Type
Description
error*
object
404Not found. A link on a suspended custom domain also returns this, so that a suspended domain cannot be told apart from a missing link.