Pages and page links
Every route for pages and their links, each with a request example and the response returned. A page is referred to by its id or by its custom address (slug).
- GET
/v1/pagesList pages - POST
/v1/pagesCreate a page - GET
/v1/pages/{id}Read a page - PATCH
/v1/pages/{id}Edit a page - DELETE
/v1/pages/{id}Delete a page - POST
/v1/pages/{id}/duplicateDuplicate a page - GET
/v1/pages/{id}/linksList a page's links - POST
/v1/pages/{id}/linksAdd a link - GET
/v1/pages/{id}/links/{lien}Read a link - PATCH
/v1/pages/{id}/links/{lien}Edit a link - DELETE
/v1/pages/{id}/links/{lien}Delete a link - PATCH
/v1/pages/{id}/linksChange several links - PUT
/v1/pages/{id}/links/orderReorder the links - PUT
/v1/pages/{id}/links/{lien}/imageChange a link's image - POST
/v1/pages/{id}/links/{lien}/imageChange a link's image - DELETE
/v1/pages/{id}/links/{lien}/imageRemove a link's image
List pages
GET/v1/pages
The environment's pages, newest first. Each page carries its views in stats: total since it was created, last_30_days over the last 30 days. Read scope.
?search=— searches the name, the custom address and the id?tag=— a tag id: only the pages that carry it?page=and?per_page=— pagination, 50 per page by default, 100 at most
curl "https://api.tinylink.fr/v1/pages?per_page=2" \
-H "Authorization: Bearer tl_your_token"
const response = await fetch('https://api.tinylink.fr/v1/pages?per_page=2', {
headers: { Authorization: 'Bearer tl_your_token' },
});
const data = await response.json();
$ch = curl_init('https://api.tinylink.fr/v1/pages?per_page=2');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => ['Authorization: Bearer tl_your_token'],
]);
$data = json_decode(curl_exec($ch), true);
curl_close($ch);
import requests
response = requests.get(
'https://api.tinylink.fr/v1/pages?per_page=2',
headers={'Authorization': 'Bearer tl_your_token'},
)
data = response.json()
Possible responses
{
"data": [
{
"id": "P6ac40109381964",
"type": "page",
"name": "My page",
"description": "All my links in one place.",
"slug": "my-page",
"url": "https://tnylnk.fr/my-page",
"status": "active",
"password_protected": false,
"restricted": false,
"tags": [],
"qr_code": null,
"created_at": "2026-10-05T21:56:57+02:00",
"edit_url": "https://app.tinylink.fr/page-edit?id=P6ac40109381964",
"stats": {
"metric": "views",
"total": 340,
"last_30_days": 85
}
}
],
"pagination": {
"page": 1,
"per_page": 2,
"total": 1,
"total_pages": 1
}
} No token in the request
{
"error": {
"code": "missing_token",
"message": "Send your token in the header: Authorization: Bearer tl_…"
}
} Unknown or revoked token
{
"error": {
"code": "invalid_token",
"message": "This token does not exist or has been revoked."
}
} The owner's plan does not include the API
{
"error": {
"code": "plan_required",
"message": "The TinyLink API is included in the Pro and Business plans. Upgrade the plan of this environment's owner to use it."
}
} The token does not carry the Read scope
{
"error": {
"code": "insufficient_scope",
"message": "This token does not have the \"read\" scope.",
"details": {
"required_scope": "read"
}
}
} More than 120 requests within the minute
{
"error": {
"code": "rate_limited",
"message": "Too many requests: 120 per minute per token."
}
} Create a page
POST/v1/pages
name is required. The response is the page created, with its links. Write scope.
name— the page's name, 100 characters at mostdescription— 2,000 characters at mostslug— the custom address: letters, digits,-,_and., 40 characters at mostpassword— protects the page with a passwordtags— a list of tag ids from the environmentqr_code—truefor the classic QR code, or a template idlinks— links to add in one go (100 at most), described as in "Add a link"
curl -X POST https://api.tinylink.fr/v1/pages \
-H "Authorization: Bearer tl_your_token" \
-H "Content-Type: application/json" \
-d '{
"name": "My page",
"slug": "my-page",
"links": [
{
"title": "My website",
"url": "https://example.com"
},
{
"title": "Contact",
"url": "hello@example.com"
}
]
}'
const response = await fetch('https://api.tinylink.fr/v1/pages', {
method: 'POST',
headers: {
Authorization: 'Bearer tl_your_token',
'Content-Type': 'application/json',
},
body: JSON.stringify({
name: 'My page',
slug: 'my-page',
links: [
{ title: 'My website', url: 'https://example.com' },
{ title: 'Contact', url: 'hello@example.com' },
],
}),
});
const data = await response.json();
$ch = curl_init('https://api.tinylink.fr/v1/pages');
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => ['Authorization: Bearer tl_your_token', 'Content-Type: application/json'],
CURLOPT_POSTFIELDS => json_encode([
'name' => 'My page',
'slug' => 'my-page',
'links' => [
['title' => 'My website', 'url' => 'https://example.com'],
['title' => 'Contact', 'url' => 'hello@example.com'],
],
]),
]);
$data = json_decode(curl_exec($ch), true);
curl_close($ch);
import requests
response = requests.post(
'https://api.tinylink.fr/v1/pages',
headers={'Authorization': 'Bearer tl_your_token'},
json={
'name': 'My page',
'slug': 'my-page',
'links': [
{'title': 'My website', 'url': 'https://example.com'},
{'title': 'Contact', 'url': 'hello@example.com'},
],
},
)
data = response.json()
Possible responses
{
"id": "P6ac40109381964",
"type": "page",
"name": "My page",
"description": "",
"slug": "my-page",
"url": "https://tnylnk.fr/my-page",
"status": "active",
"password_protected": false,
"restricted": false,
"tags": [],
"qr_code": null,
"created_at": "2026-10-05T21:56:57+02:00",
"edit_url": "https://app.tinylink.fr/page-edit?id=P6ac40109381964",
"stats": {
"metric": "views",
"total": 0,
"last_30_days": 0
},
"links": [
{
"id": "L6ac4011edb7c6",
"title": "My website",
"description": "",
"url": "https://example.com",
"type": "url",
"format": "LIST",
"size": "FULL",
"visible": true,
"archived": false,
"position": 1,
"status": "active",
"image": null,
"created_at": "2026-10-05T21:57:18+02:00"
},
{
"id": "L6ac4011ee9fab",
"title": "Contact",
"description": "",
"url": "hello@example.com",
"type": "email",
"format": "LIST",
"size": "FULL",
"visible": true,
"archived": false,
"position": 2,
"status": "active",
"image": null,
"created_at": "2026-10-05T21:57:18+02:00"
}
]
} The body is not a JSON object
{
"error": {
"code": "invalid_json",
"message": "The request body must be a JSON object."
}
} No token in the request
{
"error": {
"code": "missing_token",
"message": "Send your token in the header: Authorization: Bearer tl_…"
}
} Unknown or revoked token
{
"error": {
"code": "invalid_token",
"message": "This token does not exist or has been revoked."
}
} The plan's number of pages is reached
{
"error": {
"code": "plan_limit_reached",
"message": "The page limit of the plan has been reached."
}
} The owner's plan does not include the API
{
"error": {
"code": "plan_required",
"message": "The TinyLink API is included in the Pro and Business plans. Upgrade the plan of this environment's owner to use it."
}
} The token does not carry the Write scope
{
"error": {
"code": "insufficient_scope",
"message": "This token does not have the \"write\" scope.",
"details": {
"required_scope": "write"
}
}
} Custom address already used by a page or a link
{
"error": {
"code": "slug_taken",
"message": "This slug is already taken.",
"details": {
"field": "slug"
}
}
} Required field missing or empty
{
"error": {
"code": "validation_failed",
"message": "The \"name\" field is required.",
"details": {
"field": "name"
}
}
} More than 120 requests within the minute
{
"error": {
"code": "rate_limited",
"message": "Too many requests: 120 per minute per token."
}
} Read a page
GET/v1/pages/{id}
The page and its links, in display order; archived links come last. Read scope.
curl https://api.tinylink.fr/v1/pages/my-page \
-H "Authorization: Bearer tl_your_token"
const response = await fetch('https://api.tinylink.fr/v1/pages/my-page', {
headers: { Authorization: 'Bearer tl_your_token' },
});
const data = await response.json();
$ch = curl_init('https://api.tinylink.fr/v1/pages/my-page');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => ['Authorization: Bearer tl_your_token'],
]);
$data = json_decode(curl_exec($ch), true);
curl_close($ch);
import requests
response = requests.get(
'https://api.tinylink.fr/v1/pages/my-page',
headers={'Authorization': 'Bearer tl_your_token'},
)
data = response.json()
Possible responses
{
"id": "P6ac40109381964",
"type": "page",
"name": "My page",
"description": "All my links in one place.",
"slug": "my-page",
"url": "https://tnylnk.fr/my-page",
"status": "active",
"password_protected": false,
"restricted": false,
"tags": [],
"qr_code": null,
"created_at": "2026-10-05T21:56:57+02:00",
"edit_url": "https://app.tinylink.fr/page-edit?id=P6ac40109381964",
"stats": {
"metric": "views",
"total": 340,
"last_30_days": 85
},
"links": [
{
"id": "L6ac4011edb7c6",
"title": "My website",
"description": "",
"url": "https://example.com",
"type": "url",
"format": "LIST",
"size": "FULL",
"visible": true,
"archived": false,
"position": 1,
"status": "active",
"image": null,
"created_at": "2026-10-05T21:57:18+02:00"
},
{
"id": "L6ac4011ee9fab",
"title": "Contact",
"description": "",
"url": "hello@example.com",
"type": "email",
"format": "LIST",
"size": "FULL",
"visible": true,
"archived": false,
"position": 2,
"status": "active",
"image": null,
"created_at": "2026-10-05T21:57:18+02:00"
}
]
} No token in the request
{
"error": {
"code": "missing_token",
"message": "Send your token in the header: Authorization: Bearer tl_…"
}
} Unknown or revoked token
{
"error": {
"code": "invalid_token",
"message": "This token does not exist or has been revoked."
}
} The owner's plan does not include the API
{
"error": {
"code": "plan_required",
"message": "The TinyLink API is included in the Pro and Business plans. Upgrade the plan of this environment's owner to use it."
}
} The token does not carry the Read scope
{
"error": {
"code": "insufficient_scope",
"message": "This token does not have the \"read\" scope.",
"details": {
"required_scope": "read"
}
}
} No page with this id or slug in the environment
{
"error": {
"code": "not_found",
"message": "Page not found in this environment."
}
} More than 120 requests within the minute
{
"error": {
"code": "rate_limited",
"message": "Too many requests: 120 per minute per token."
}
} Edit a page
PATCH/v1/pages/{id}
Only send the fields to change: name, description, slug, password. null removes the custom address or the password. The response is the updated page. Write scope.
curl -X PATCH https://api.tinylink.fr/v1/pages/P6ac40109381964 \
-H "Authorization: Bearer tl_your_token" \
-H "Content-Type: application/json" \
-d '{"description":"All my links in one place.","password":null}'
const response = await fetch('https://api.tinylink.fr/v1/pages/P6ac40109381964', {
method: 'PATCH',
headers: {
Authorization: 'Bearer tl_your_token',
'Content-Type': 'application/json',
},
body: JSON.stringify({ description: 'All my links in one place.', password: null }),
});
const data = await response.json();
$ch = curl_init('https://api.tinylink.fr/v1/pages/P6ac40109381964');
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'PATCH',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => ['Authorization: Bearer tl_your_token', 'Content-Type: application/json'],
CURLOPT_POSTFIELDS => json_encode([
'description' => 'All my links in one place.',
'password' => null,
]),
]);
$data = json_decode(curl_exec($ch), true);
curl_close($ch);
import requests
response = requests.patch(
'https://api.tinylink.fr/v1/pages/P6ac40109381964',
headers={'Authorization': 'Bearer tl_your_token'},
json={'description': 'All my links in one place.', 'password': None},
)
data = response.json()
Possible responses
{
"id": "P6ac40109381964",
"type": "page",
"name": "My page",
"description": "All my links in one place.",
"slug": "my-page",
"url": "https://tnylnk.fr/my-page",
"status": "active",
"password_protected": false,
"restricted": false,
"tags": [],
"qr_code": null,
"created_at": "2026-10-05T21:56:57+02:00",
"edit_url": "https://app.tinylink.fr/page-edit?id=P6ac40109381964",
"stats": {
"metric": "views",
"total": 340,
"last_30_days": 85
},
"links": [
{
"id": "L6ac4011edb7c6",
"title": "My website",
"description": "",
"url": "https://example.com",
"type": "url",
"format": "LIST",
"size": "FULL",
"visible": true,
"archived": false,
"position": 1,
"status": "active",
"image": null,
"created_at": "2026-10-05T21:57:18+02:00"
},
{
"id": "L6ac4011ee9fab",
"title": "Contact",
"description": "",
"url": "hello@example.com",
"type": "email",
"format": "LIST",
"size": "FULL",
"visible": true,
"archived": false,
"position": 2,
"status": "active",
"image": null,
"created_at": "2026-10-05T21:57:18+02:00"
}
]
} The body is not a JSON object
{
"error": {
"code": "invalid_json",
"message": "The request body must be a JSON object."
}
} No token in the request
{
"error": {
"code": "missing_token",
"message": "Send your token in the header: Authorization: Bearer tl_…"
}
} Unknown or revoked token
{
"error": {
"code": "invalid_token",
"message": "This token does not exist or has been revoked."
}
} The owner's plan does not include the API
{
"error": {
"code": "plan_required",
"message": "The TinyLink API is included in the Pro and Business plans. Upgrade the plan of this environment's owner to use it."
}
} The token does not carry the Write scope
{
"error": {
"code": "insufficient_scope",
"message": "This token does not have the \"write\" scope.",
"details": {
"required_scope": "write"
}
}
} No page with this id or slug in the environment
{
"error": {
"code": "not_found",
"message": "Page not found in this environment."
}
} Custom address already used by a page or a link
{
"error": {
"code": "slug_taken",
"message": "This slug is already taken.",
"details": {
"field": "slug"
}
}
} No editable field in the body
{
"error": {
"code": "validation_failed",
"message": "Nothing to update. Accepted fields: name, description, slug, password."
}
} Element blocked by moderation
{
"error": {
"code": "element_blocked",
"message": "This element is blocked by moderation and can no longer be modified."
}
} More than 120 requests within the minute
{
"error": {
"code": "rate_limited",
"message": "Too many requests: 120 per minute per token."
}
} Delete a page
DELETE/v1/pages/{id}
Deletes the page, its links and its statistics. This cannot be undone. Delete scope.
curl -X DELETE https://api.tinylink.fr/v1/pages/P6ac40109381964 \
-H "Authorization: Bearer tl_your_token"
const response = await fetch('https://api.tinylink.fr/v1/pages/P6ac40109381964', {
method: 'DELETE',
headers: { Authorization: 'Bearer tl_your_token' },
});
console.log(response.status); // 204
$ch = curl_init('https://api.tinylink.fr/v1/pages/P6ac40109381964');
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'DELETE',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => ['Authorization: Bearer tl_your_token'],
]);
curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE); // 204
curl_close($ch);
import requests
response = requests.delete(
'https://api.tinylink.fr/v1/pages/P6ac40109381964',
headers={'Authorization': 'Bearer tl_your_token'},
)
print(response.status_code) # 204
Possible responses
No content
No token in the request
{
"error": {
"code": "missing_token",
"message": "Send your token in the header: Authorization: Bearer tl_…"
}
} Unknown or revoked token
{
"error": {
"code": "invalid_token",
"message": "This token does not exist or has been revoked."
}
} The owner's plan does not include the API
{
"error": {
"code": "plan_required",
"message": "The TinyLink API is included in the Pro and Business plans. Upgrade the plan of this environment's owner to use it."
}
} The token does not carry the Delete scope
{
"error": {
"code": "insufficient_scope",
"message": "This token does not have the \"delete\" scope.",
"details": {
"required_scope": "delete"
}
}
} No page with this id or slug in the environment
{
"error": {
"code": "not_found",
"message": "Page not found in this environment."
}
} More than 120 requests within the minute
{
"error": {
"code": "rate_limited",
"message": "Too many requests: 120 per minute per token."
}
} Duplicate a page
POST/v1/pages/{id}/duplicate
Creates a copy of the page in the same environment: appearance settings and followed style, logo and banner, every link, title, component and integration block, in the same order, with their visibility, archiving and images (files of the copy's own). Neither the custom address, nor the password, nor the tags, nor the QR code are carried over. name (otherwise the same name) and slug are optional. The plan's page limit applies. Write scope.
curl -X POST https://api.tinylink.fr/v1/pages/P6ad34a0e4fef09/duplicate \
-H "Authorization: Bearer tl_your_token" \
-H "Content-Type: application/json" \
-d '{"name":"Ma page (copie)","slug":"ma-page-copie"}'
const response = await fetch('https://api.tinylink.fr/v1/pages/P6ad34a0e4fef09/duplicate', {
method: 'POST',
headers: {
Authorization: 'Bearer tl_your_token',
'Content-Type': 'application/json',
},
body: JSON.stringify({ name: 'Ma page (copie)', slug: 'ma-page-copie' }),
});
const data = await response.json();
$ch = curl_init('https://api.tinylink.fr/v1/pages/P6ad34a0e4fef09/duplicate');
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => ['Authorization: Bearer tl_your_token', 'Content-Type: application/json'],
CURLOPT_POSTFIELDS => json_encode(['name' => 'Ma page (copie)', 'slug' => 'ma-page-copie']),
]);
$data = json_decode(curl_exec($ch), true);
curl_close($ch);
import requests
response = requests.post(
'https://api.tinylink.fr/v1/pages/P6ad34a0e4fef09/duplicate',
headers={'Authorization': 'Bearer tl_your_token'},
json={'name': 'Ma page (copie)', 'slug': 'ma-page-copie'},
)
data = response.json()
Possible responses
{
"id": "P6ad34edcdd6ab6",
"type": "page",
"name": "Ma page (copie)",
"description": "",
"slug": "ma-page-copie",
"url": "https://tnylnk.fr/ma-page-copie",
"status": "active",
"password_protected": false,
"restricted": false,
"tags": [],
"qr_code": null,
"created_at": "2026-10-17T12:33:00+02:00",
"edit_url": "https://app.tinylink.fr/page-edit?id=P6ad34edcdd6ab6",
"stats": {
"metric": "views",
"total": 0,
"last_30_days": 0
},
"links": [
{
"id": "L6ad34edcdd9c3",
"title": "Site",
"description": "",
"url": "https://exemple.fr",
"type": "url",
"format": "LIST",
"size": "FULL",
"visible": true,
"archived": false,
"position": 1,
"status": "active",
"image": "https://content.tinylink.fr/page-image/logo_6ad34edcdd8b7.webp",
"created_at": "2026-10-17T12:33:00+02:00"
},
{
"id": "L6ad34edcddab2",
"title": "Section",
"description": "",
"url": null,
"type": "title",
"format": "TITLE",
"size": "FULL",
"visible": true,
"archived": false,
"position": 2,
"status": "active",
"image": null,
"created_at": "2026-10-17T12:33:00+02:00"
},
{
"id": "L6ad34edcddb85",
"title": "Caché",
"description": "",
"url": "https://exemple.org",
"type": "url",
"format": "LIST",
"size": "FULL",
"visible": false,
"archived": false,
"position": 3,
"status": "active",
"image": null,
"created_at": "2026-10-17T12:33:00+02:00"
},
{
"id": "L6ad34edcddc64",
"title": "Mes réseaux",
"description": null,
"url": null,
"type": "component",
"format": "COMPONENT",
"size": "FULL",
"visible": true,
"archived": false,
"position": 4,
"status": "active",
"image": null,
"created_at": "2026-10-17T12:33:00+02:00",
"component_id": "C6ad34ed4599305"
}
]
} The body is not a JSON object
{
"error": {
"code": "invalid_json",
"message": "The request body must be a JSON object."
}
} No token in the request
{
"error": {
"code": "missing_token",
"message": "Send your token in the header: Authorization: Bearer tl_…"
}
} Unknown or revoked token
{
"error": {
"code": "invalid_token",
"message": "This token does not exist or has been revoked."
}
} The plan's number of pages is reached
{
"error": {
"code": "plan_limit_reached",
"message": "The page limit of the plan has been reached."
}
} The owner's plan does not include the API
{
"error": {
"code": "plan_required",
"message": "The TinyLink API is included in the Pro and Business plans. Upgrade the plan of this environment's owner to use it."
}
} The token does not carry the Write scope
{
"error": {
"code": "insufficient_scope",
"message": "This token does not have the \"write\" scope.",
"details": {
"required_scope": "write"
}
}
} No page with this id or slug in the environment
{
"error": {
"code": "not_found",
"message": "Page not found in this environment."
}
} Custom address already used by a page or a link
{
"error": {
"code": "slug_taken",
"message": "This slug is already taken.",
"details": {
"field": "slug"
}
}
} Required field missing or empty
{
"error": {
"code": "validation_failed",
"message": "The \"name\" field is required.",
"details": {
"field": "name"
}
}
} More than 120 requests within the minute
{
"error": {
"code": "rate_limited",
"message": "Too many requests: 120 per minute per token."
}
} List a page's links
GET/v1/pages/{id}/links
The page's links, in display order. type is url, email, tel, title, component (a component placed on the page, with component_id) or integration (an integration block, with integration); status is active, pending_review or blocked. Read scope.
curl https://api.tinylink.fr/v1/pages/P6ac40109381964/links \
-H "Authorization: Bearer tl_your_token"
const response = await fetch('https://api.tinylink.fr/v1/pages/P6ac40109381964/links', {
headers: { Authorization: 'Bearer tl_your_token' },
});
const data = await response.json();
$ch = curl_init('https://api.tinylink.fr/v1/pages/P6ac40109381964/links');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => ['Authorization: Bearer tl_your_token'],
]);
$data = json_decode(curl_exec($ch), true);
curl_close($ch);
import requests
response = requests.get(
'https://api.tinylink.fr/v1/pages/P6ac40109381964/links',
headers={'Authorization': 'Bearer tl_your_token'},
)
data = response.json()
Possible responses
{
"data": [
{
"id": "L6ac4011edb7c6",
"title": "My website",
"description": "",
"url": "https://example.com",
"type": "url",
"format": "LIST",
"size": "FULL",
"visible": true,
"archived": false,
"position": 1,
"status": "active",
"image": null,
"created_at": "2026-10-05T21:57:18+02:00"
},
{
"id": "L6ac4011eeb074",
"title": "My socials",
"description": "",
"url": null,
"type": "title",
"format": "TITLE",
"size": "FULL",
"visible": true,
"archived": false,
"position": 2,
"status": "active",
"image": null,
"created_at": "2026-10-05T21:57:18+02:00"
}
]
} No token in the request
{
"error": {
"code": "missing_token",
"message": "Send your token in the header: Authorization: Bearer tl_…"
}
} Unknown or revoked token
{
"error": {
"code": "invalid_token",
"message": "This token does not exist or has been revoked."
}
} The owner's plan does not include the API
{
"error": {
"code": "plan_required",
"message": "The TinyLink API is included in the Pro and Business plans. Upgrade the plan of this environment's owner to use it."
}
} The token does not carry the Read scope
{
"error": {
"code": "insufficient_scope",
"message": "This token does not have the \"read\" scope.",
"details": {
"required_scope": "read"
}
}
} No page with this id or slug in the environment
{
"error": {
"code": "not_found",
"message": "Page not found in this environment."
}
} More than 120 requests within the minute
{
"error": {
"code": "rate_limited",
"message": "Too many requests: 120 per minute per token."
}
} Add a link
POST/v1/pages/{id}/links
Adds a link at the bottom of the page, or several with {"links": [ … ]} (100 at most): the response is then {"data": [ … ]}. Your plan's link limits apply as in the app. Write scope.
title— required, except for theSOCIALformat; 100 characters at mosturl— a web address, an e-mail or a phone number, with or withoutmailto:/tel:; not needed for aTITLEdescription— 1,000 characters at mostformat—LIST(default),BANNER,SQUARE,SOCIAL, orTITLEfor a section titlesize—FULL(default) orHALF, forLIST,BANNERandSQUAREvisible—falseto add it hiddenposition— rank in the page, 1 = topimage— the public address of an image or a base64 data URI, cropped as a square and as a banner;crop.squareandcrop.banner({"x", "y", "w", "h"}) pick the areasintegration_id,source… — for a block fed by a connected account, see Integrations
curl -X POST https://api.tinylink.fr/v1/pages/P6ac40109381964/links \
-H "Authorization: Bearer tl_your_token" \
-H "Content-Type: application/json" \
-d '{"title":"My website","url":"https://example.com"}'
const response = await fetch('https://api.tinylink.fr/v1/pages/P6ac40109381964/links', {
method: 'POST',
headers: {
Authorization: 'Bearer tl_your_token',
'Content-Type': 'application/json',
},
body: JSON.stringify({ title: 'My website', url: 'https://example.com' }),
});
const data = await response.json();
$ch = curl_init('https://api.tinylink.fr/v1/pages/P6ac40109381964/links');
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => ['Authorization: Bearer tl_your_token', 'Content-Type: application/json'],
CURLOPT_POSTFIELDS => json_encode(['title' => 'My website', 'url' => 'https://example.com']),
]);
$data = json_decode(curl_exec($ch), true);
curl_close($ch);
import requests
response = requests.post(
'https://api.tinylink.fr/v1/pages/P6ac40109381964/links',
headers={'Authorization': 'Bearer tl_your_token'},
json={'title': 'My website', 'url': 'https://example.com'},
)
data = response.json()
Possible responses
{
"id": "L6ac4011edb7c6",
"title": "My website",
"description": "",
"url": "https://example.com",
"type": "url",
"format": "LIST",
"size": "FULL",
"visible": true,
"archived": false,
"position": 1,
"status": "active",
"image": null,
"created_at": "2026-10-05T21:57:18+02:00"
} The body is not a JSON object
{
"error": {
"code": "invalid_json",
"message": "The request body must be a JSON object."
}
} No token in the request
{
"error": {
"code": "missing_token",
"message": "Send your token in the header: Authorization: Bearer tl_…"
}
} Unknown or revoked token
{
"error": {
"code": "invalid_token",
"message": "This token does not exist or has been revoked."
}
} The plan's number of links per page is reached
{
"error": {
"code": "plan_limit_reached",
"message": "The plan allows 50 links per page (50 already used).",
"details": {
"max": 50,
"used": 50
}
}
} The owner's plan does not include the API
{
"error": {
"code": "plan_required",
"message": "The TinyLink API is included in the Pro and Business plans. Upgrade the plan of this environment's owner to use it."
}
} The token does not carry the Write scope
{
"error": {
"code": "insufficient_scope",
"message": "This token does not have the \"write\" scope.",
"details": {
"required_scope": "write"
}
}
} No page with this id or slug in the environment
{
"error": {
"code": "not_found",
"message": "Page not found in this environment."
}
} Required field missing or empty
{
"error": {
"code": "validation_failed",
"message": "The \"title\" field is required.",
"details": {
"field": "title"
}
}
} Neither a web address, nor an e-mail, nor a phone number
{
"error": {
"code": "invalid_url",
"message": "This is not a valid web address, e-mail address or phone number.",
"details": {
"field": "url"
}
}
} Domain flagged as suspicious
{
"error": {
"code": "suspicious_url",
"message": "This address is on our list of suspicious domains and cannot be used.",
"details": {
"field": "url"
}
}
} Element blocked by moderation
{
"error": {
"code": "element_blocked",
"message": "This element is blocked by moderation and can no longer be modified."
}
} More than 120 requests within the minute
{
"error": {
"code": "rate_limited",
"message": "Too many requests: 120 per minute per token."
}
} Read a link
GET/v1/pages/{id}/links/{lien}
A single link of the page, by its id. Read scope.
curl https://api.tinylink.fr/v1/pages/P6ac40109381964/links/L6ac4011edb7c6 \
-H "Authorization: Bearer tl_your_token"
const response = await fetch('https://api.tinylink.fr/v1/pages/P6ac40109381964/links/L6ac4011edb7c6', {
headers: { Authorization: 'Bearer tl_your_token' },
});
const data = await response.json();
$ch = curl_init('https://api.tinylink.fr/v1/pages/P6ac40109381964/links/L6ac4011edb7c6');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => ['Authorization: Bearer tl_your_token'],
]);
$data = json_decode(curl_exec($ch), true);
curl_close($ch);
import requests
response = requests.get(
'https://api.tinylink.fr/v1/pages/P6ac40109381964/links/L6ac4011edb7c6',
headers={'Authorization': 'Bearer tl_your_token'},
)
data = response.json()
Possible responses
{
"id": "L6ac4011edb7c6",
"title": "My website",
"description": "",
"url": "https://example.com",
"type": "url",
"format": "LIST",
"size": "FULL",
"visible": true,
"archived": false,
"position": 1,
"status": "active",
"image": null,
"created_at": "2026-10-05T21:57:18+02:00"
} No token in the request
{
"error": {
"code": "missing_token",
"message": "Send your token in the header: Authorization: Bearer tl_…"
}
} Unknown or revoked token
{
"error": {
"code": "invalid_token",
"message": "This token does not exist or has been revoked."
}
} The owner's plan does not include the API
{
"error": {
"code": "plan_required",
"message": "The TinyLink API is included in the Pro and Business plans. Upgrade the plan of this environment's owner to use it."
}
} The token does not carry the Read scope
{
"error": {
"code": "insufficient_scope",
"message": "This token does not have the \"read\" scope.",
"details": {
"required_scope": "read"
}
}
} No page with this id or slug in the environment
{
"error": {
"code": "not_found",
"message": "Page not found in this environment."
}
} No link with this id on the page
{
"error": {
"code": "not_found",
"message": "Link not found on this page."
}
} More than 120 requests within the minute
{
"error": {
"code": "rate_limited",
"message": "Too many requests: 120 per minute per token."
}
} Edit a link
PATCH/v1/pages/{id}/links/{lien}
Only send the fields to change: title, description, url, format, size, visible (hide or show), archived (archive or unarchive) , position (move) and image (as when adding; null removes it). A component can only be hidden, archived or moved; an integration block has its own fields, see Integrations. Write scope.
curl -X PATCH https://api.tinylink.fr/v1/pages/P6ac40109381964/links/L6ac4011edb7c6 \
-H "Authorization: Bearer tl_your_token" \
-H "Content-Type: application/json" \
-d '{"title":"My new website","position":2,"visible":false}'
const response = await fetch('https://api.tinylink.fr/v1/pages/P6ac40109381964/links/L6ac4011edb7c6', {
method: 'PATCH',
headers: {
Authorization: 'Bearer tl_your_token',
'Content-Type': 'application/json',
},
body: JSON.stringify({ title: 'My new website', position: 2, visible: false }),
});
const data = await response.json();
$ch = curl_init('https://api.tinylink.fr/v1/pages/P6ac40109381964/links/L6ac4011edb7c6');
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'PATCH',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => ['Authorization: Bearer tl_your_token', 'Content-Type: application/json'],
CURLOPT_POSTFIELDS => json_encode([
'title' => 'My new website',
'position' => 2,
'visible' => false,
]),
]);
$data = json_decode(curl_exec($ch), true);
curl_close($ch);
import requests
response = requests.patch(
'https://api.tinylink.fr/v1/pages/P6ac40109381964/links/L6ac4011edb7c6',
headers={'Authorization': 'Bearer tl_your_token'},
json={'title': 'My new website', 'position': 2, 'visible': False},
)
data = response.json()
Possible responses
{
"id": "L6ac4011edb7c6",
"title": "My new website",
"description": "",
"url": "https://example.com",
"type": "url",
"format": "LIST",
"size": "FULL",
"visible": false,
"archived": false,
"position": 2,
"status": "active",
"image": null,
"created_at": "2026-10-05T21:57:18+02:00"
} The body is not a JSON object
{
"error": {
"code": "invalid_json",
"message": "The request body must be a JSON object."
}
} No token in the request
{
"error": {
"code": "missing_token",
"message": "Send your token in the header: Authorization: Bearer tl_…"
}
} Unknown or revoked token
{
"error": {
"code": "invalid_token",
"message": "This token does not exist or has been revoked."
}
} The owner's plan does not include the API
{
"error": {
"code": "plan_required",
"message": "The TinyLink API is included in the Pro and Business plans. Upgrade the plan of this environment's owner to use it."
}
} The token does not carry the Write scope
{
"error": {
"code": "insufficient_scope",
"message": "This token does not have the \"write\" scope.",
"details": {
"required_scope": "write"
}
}
} No page with this id or slug in the environment
{
"error": {
"code": "not_found",
"message": "Page not found in this environment."
}
} No link with this id on the page
{
"error": {
"code": "not_found",
"message": "Link not found on this page."
}
} No editable field in the body
{
"error": {
"code": "validation_failed",
"message": "Nothing to update. Accepted fields: title, description, url, format, size, visible, archived, position, image."
}
} Neither a web address, nor an e-mail, nor a phone number
{
"error": {
"code": "invalid_url",
"message": "This is not a valid web address, e-mail address or phone number.",
"details": {
"field": "url"
}
}
} Element blocked by moderation
{
"error": {
"code": "element_blocked",
"message": "This element is blocked by moderation and can no longer be modified."
}
} More than 120 requests within the minute
{
"error": {
"code": "rate_limited",
"message": "Too many requests: 120 per minute per token."
}
} Delete a link
DELETE/v1/pages/{id}/links/{lien}
Deletes the link, its image and its statistics, then renumbers the following ones. Delete scope.
curl -X DELETE https://api.tinylink.fr/v1/pages/P6ac40109381964/links/L6ac4011edb7c6 \
-H "Authorization: Bearer tl_your_token"
const response = await fetch('https://api.tinylink.fr/v1/pages/P6ac40109381964/links/L6ac4011edb7c6', {
method: 'DELETE',
headers: { Authorization: 'Bearer tl_your_token' },
});
console.log(response.status); // 204
$ch = curl_init('https://api.tinylink.fr/v1/pages/P6ac40109381964/links/L6ac4011edb7c6');
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'DELETE',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => ['Authorization: Bearer tl_your_token'],
]);
curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE); // 204
curl_close($ch);
import requests
response = requests.delete(
'https://api.tinylink.fr/v1/pages/P6ac40109381964/links/L6ac4011edb7c6',
headers={'Authorization': 'Bearer tl_your_token'},
)
print(response.status_code) # 204
Possible responses
No content
No token in the request
{
"error": {
"code": "missing_token",
"message": "Send your token in the header: Authorization: Bearer tl_…"
}
} Unknown or revoked token
{
"error": {
"code": "invalid_token",
"message": "This token does not exist or has been revoked."
}
} The owner's plan does not include the API
{
"error": {
"code": "plan_required",
"message": "The TinyLink API is included in the Pro and Business plans. Upgrade the plan of this environment's owner to use it."
}
} The token does not carry the Delete scope
{
"error": {
"code": "insufficient_scope",
"message": "This token does not have the \"delete\" scope.",
"details": {
"required_scope": "delete"
}
}
} No page with this id or slug in the environment
{
"error": {
"code": "not_found",
"message": "Page not found in this environment."
}
} No link with this id on the page
{
"error": {
"code": "not_found",
"message": "Link not found on this page."
}
} More than 120 requests within the minute
{
"error": {
"code": "rate_limited",
"message": "Too many requests: 120 per minute per token."
}
} Change several links
PATCH/v1/pages/{id}/links
Changes several links in one request — for example the layout of a whole series: links lists up to 100 entries {"id": …} followed by the fields to change, as for a single link. All or nothing: at the first error nothing is saved, and the faulty field is named (links[1].url). Images are sent one link at a time. The response is the list of the page's links. Write scope.
curl -X PATCH https://api.tinylink.fr/v1/pages/P6ad34a0e4fef09/links \
-H "Authorization: Bearer tl_your_token" \
-H "Content-Type: application/json" \
-d '{
"links": [
{
"id": "L6ad34a0e84122",
"format": "BANNER",
"size": "HALF"
},
{
"id": "L6ad34a0e8467f",
"format": "BANNER",
"size": "HALF"
}
]
}'
const response = await fetch('https://api.tinylink.fr/v1/pages/P6ad34a0e4fef09/links', {
method: 'PATCH',
headers: {
Authorization: 'Bearer tl_your_token',
'Content-Type': 'application/json',
},
body: JSON.stringify({
links: [
{ id: 'L6ad34a0e84122', format: 'BANNER', size: 'HALF' },
{ id: 'L6ad34a0e8467f', format: 'BANNER', size: 'HALF' },
],
}),
});
const data = await response.json();
$ch = curl_init('https://api.tinylink.fr/v1/pages/P6ad34a0e4fef09/links');
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'PATCH',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => ['Authorization: Bearer tl_your_token', 'Content-Type: application/json'],
CURLOPT_POSTFIELDS => json_encode([
'links' => [
[
'id' => 'L6ad34a0e84122',
'format' => 'BANNER',
'size' => 'HALF',
],
[
'id' => 'L6ad34a0e8467f',
'format' => 'BANNER',
'size' => 'HALF',
],
],
]),
]);
$data = json_decode(curl_exec($ch), true);
curl_close($ch);
import requests
response = requests.patch(
'https://api.tinylink.fr/v1/pages/P6ad34a0e4fef09/links',
headers={'Authorization': 'Bearer tl_your_token'},
json={
'links': [
{'id': 'L6ad34a0e84122', 'format': 'BANNER', 'size': 'HALF'},
{'id': 'L6ad34a0e8467f', 'format': 'BANNER', 'size': 'HALF'},
],
},
)
data = response.json()
Possible responses
{
"data": [
{
"id": "L6ad34a0e849a2",
"title": "Mes réseaux",
"description": "",
"url": null,
"type": "title",
"format": "TITLE",
"size": "FULL",
"visible": true,
"archived": false,
"position": 1,
"status": "active",
"image": null,
"created_at": "2026-10-17T12:12:30+02:00"
},
{
"id": "L6ad34a0e84122",
"title": "Mon site",
"description": "",
"url": "https://exemple.fr",
"type": "url",
"format": "BANNER",
"size": "HALF",
"visible": true,
"archived": false,
"position": 2,
"status": "active",
"image": null,
"created_at": "2026-10-17T12:12:30+02:00"
},
{
"id": "L6ad34a0e8467f",
"title": "Ma boutique",
"description": "",
"url": "https://exemple.fr/boutique",
"type": "url",
"format": "BANNER",
"size": "HALF",
"visible": true,
"archived": false,
"position": 3,
"status": "active",
"image": null,
"created_at": "2026-10-17T12:12:30+02:00"
}
]
} The body is not a JSON object
{
"error": {
"code": "invalid_json",
"message": "The request body must be a JSON object."
}
} No token in the request
{
"error": {
"code": "missing_token",
"message": "Send your token in the header: Authorization: Bearer tl_…"
}
} Unknown or revoked token
{
"error": {
"code": "invalid_token",
"message": "This token does not exist or has been revoked."
}
} The owner's plan does not include the API
{
"error": {
"code": "plan_required",
"message": "The TinyLink API is included in the Pro and Business plans. Upgrade the plan of this environment's owner to use it."
}
} The token does not carry the Write scope
{
"error": {
"code": "insufficient_scope",
"message": "This token does not have the \"write\" scope.",
"details": {
"required_scope": "write"
}
}
} No page with this id or slug in the environment
{
"error": {
"code": "not_found",
"message": "Page not found in this environment."
}
} No link with this id on the page
{
"error": {
"code": "not_found",
"message": "Link not found on this page."
}
} List of links missing or empty
{
"error": {
"code": "validation_failed",
"message": "The \"links\" field must be a non-empty array of { \"id\": …, fields to change }.",
"details": {
"field": "links"
}
}
} Neither a web address, nor an e-mail, nor a phone number
{
"error": {
"code": "invalid_url",
"message": "This is not a valid web address, e-mail address or phone number.",
"details": {
"field": "url"
}
}
} Component block: only visibility, archiving and position change
{
"error": {
"code": "validation_failed",
"message": "A component block can only be shown, hidden, archived or moved here: edit the component itself through /v1/components."
}
} Element blocked by moderation
{
"error": {
"code": "element_blocked",
"message": "This element is blocked by moderation and can no longer be modified."
}
} More than 120 requests within the minute
{
"error": {
"code": "rate_limited",
"message": "Too many requests: 120 per minute per token."
}
} Reorder the links
PUT/v1/pages/{id}/links/order
ids gives the new order: the links, titles and components listed move to the top, in that order; the others follow in their current order. The response is the list of the page's links. Write scope.
curl -X PUT https://api.tinylink.fr/v1/pages/P6ad34a0e4fef09/links/order \
-H "Authorization: Bearer tl_your_token" \
-H "Content-Type: application/json" \
-d '{"ids":["L6ad34a0e849a2","L6ad34a0e84122"]}'
const response = await fetch('https://api.tinylink.fr/v1/pages/P6ad34a0e4fef09/links/order', {
method: 'PUT',
headers: {
Authorization: 'Bearer tl_your_token',
'Content-Type': 'application/json',
},
body: JSON.stringify({ ids: ['L6ad34a0e849a2', 'L6ad34a0e84122'] }),
});
const data = await response.json();
$ch = curl_init('https://api.tinylink.fr/v1/pages/P6ad34a0e4fef09/links/order');
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'PUT',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => ['Authorization: Bearer tl_your_token', 'Content-Type: application/json'],
CURLOPT_POSTFIELDS => json_encode(['ids' => ['L6ad34a0e849a2', 'L6ad34a0e84122']]),
]);
$data = json_decode(curl_exec($ch), true);
curl_close($ch);
import requests
response = requests.put(
'https://api.tinylink.fr/v1/pages/P6ad34a0e4fef09/links/order',
headers={'Authorization': 'Bearer tl_your_token'},
json={'ids': ['L6ad34a0e849a2', 'L6ad34a0e84122']},
)
data = response.json()
Possible responses
{
"data": [
{
"id": "L6ad34a0e849a2",
"title": "Mes réseaux",
"description": "",
"url": null,
"type": "title",
"format": "TITLE",
"size": "FULL",
"visible": true,
"archived": false,
"position": 1,
"status": "active",
"image": null,
"created_at": "2026-10-17T12:12:30+02:00"
},
{
"id": "L6ad34a0e84122",
"title": "Mon site",
"description": "",
"url": "https://exemple.fr",
"type": "url",
"format": "LIST",
"size": "FULL",
"visible": true,
"archived": false,
"position": 2,
"status": "active",
"image": null,
"created_at": "2026-10-17T12:12:30+02:00"
},
{
"id": "L6ad34a0e8467f",
"title": "Ma boutique",
"description": "",
"url": "https://exemple.fr/boutique",
"type": "url",
"format": "LIST",
"size": "FULL",
"visible": true,
"archived": false,
"position": 3,
"status": "active",
"image": null,
"created_at": "2026-10-17T12:12:30+02:00"
}
]
} The body is not a JSON object
{
"error": {
"code": "invalid_json",
"message": "The request body must be a JSON object."
}
} No token in the request
{
"error": {
"code": "missing_token",
"message": "Send your token in the header: Authorization: Bearer tl_…"
}
} Unknown or revoked token
{
"error": {
"code": "invalid_token",
"message": "This token does not exist or has been revoked."
}
} The owner's plan does not include the API
{
"error": {
"code": "plan_required",
"message": "The TinyLink API is included in the Pro and Business plans. Upgrade the plan of this environment's owner to use it."
}
} The token does not carry the Write scope
{
"error": {
"code": "insufficient_scope",
"message": "This token does not have the \"write\" scope.",
"details": {
"required_scope": "write"
}
}
} No page with this id or slug in the environment
{
"error": {
"code": "not_found",
"message": "Page not found in this environment."
}
} Id that is not a block of the page
{
"error": {
"code": "validation_failed",
"message": "Unknown link id: L6ac4011edb7c6.",
"details": {
"field": "ids[0]"
}
}
} Element blocked by moderation
{
"error": {
"code": "element_blocked",
"message": "This element is blocked by moderation and can no longer be modified."
}
} More than 120 requests within the minute
{
"error": {
"code": "rate_limited",
"message": "Too many requests: 120 per minute per token."
}
} Change a link's image
PUT/v1/pages/{id}/links/{lien}/image
POST/v1/pages/{id}/links/{lien}/image
image: the public address of an image or a base64 data URI; to upload a file, POST as multipart/form-data with an image field. JPEG, PNG or WebP, 5 MB at most. Two formats are produced: a square (LIST, SQUARE formats) and a banner (BANNER), each croppable with crop.square and crop.banner. A title or a component takes no image. Write scope.
curl -X PUT https://api.tinylink.fr/v1/pages/P6ad34a0e4fef09/links/L6ad34a0e84122/image \
-H "Authorization: Bearer tl_your_token" \
-H "Content-Type: application/json" \
-d '{
"image": "https://exemple.fr/visuel.jpg",
"crop": {
"square": {
"x": 0,
"y": 0,
"w": 800,
"h": 800
}
}
}'
const response = await fetch('https://api.tinylink.fr/v1/pages/P6ad34a0e4fef09/links/L6ad34a0e84122/image', {
method: 'PUT',
headers: {
Authorization: 'Bearer tl_your_token',
'Content-Type': 'application/json',
},
body: JSON.stringify({
image: 'https://exemple.fr/visuel.jpg',
crop: { square: { x: 0, y: 0, w: 800, h: 800 } },
}),
});
const data = await response.json();
$ch = curl_init('https://api.tinylink.fr/v1/pages/P6ad34a0e4fef09/links/L6ad34a0e84122/image');
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'PUT',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => ['Authorization: Bearer tl_your_token', 'Content-Type: application/json'],
CURLOPT_POSTFIELDS => json_encode([
'image' => 'https://exemple.fr/visuel.jpg',
'crop' => ['square' => ['x' => 0, 'y' => 0, 'w' => 800, 'h' => 800]],
]),
]);
$data = json_decode(curl_exec($ch), true);
curl_close($ch);
import requests
response = requests.put(
'https://api.tinylink.fr/v1/pages/P6ad34a0e4fef09/links/L6ad34a0e84122/image',
headers={'Authorization': 'Bearer tl_your_token'},
json={
'image': 'https://exemple.fr/visuel.jpg',
'crop': {'square': {'x': 0, 'y': 0, 'w': 800, 'h': 800}},
},
)
data = response.json()
Possible responses
{
"id": "L6ad34a0e84122",
"title": "Mon site",
"description": "",
"url": "https://exemple.fr",
"type": "url",
"format": "LIST",
"size": "FULL",
"visible": true,
"archived": false,
"position": 1,
"status": "active",
"image": "https://content.tinylink.fr/page-image/logo_6ad34a0e8e7da.webp",
"created_at": "2026-10-17T12:12:30+02:00"
} The body is not a JSON object
{
"error": {
"code": "invalid_json",
"message": "The request body must be a JSON object."
}
} No token in the request
{
"error": {
"code": "missing_token",
"message": "Send your token in the header: Authorization: Bearer tl_…"
}
} Unknown or revoked token
{
"error": {
"code": "invalid_token",
"message": "This token does not exist or has been revoked."
}
} The owner's plan does not include the API
{
"error": {
"code": "plan_required",
"message": "The TinyLink API is included in the Pro and Business plans. Upgrade the plan of this environment's owner to use it."
}
} The token does not carry the Write scope
{
"error": {
"code": "insufficient_scope",
"message": "This token does not have the \"write\" scope.",
"details": {
"required_scope": "write"
}
}
} No page with this id or slug in the environment
{
"error": {
"code": "not_found",
"message": "Page not found in this environment."
}
} No link with this id on the page
{
"error": {
"code": "not_found",
"message": "Link not found on this page."
}
} Image unreadable, too heavy or in a refused format
{
"error": {
"code": "invalid_image",
"message": "The image could not be used: send a JPEG, PNG or WebP image (5 MB and 6000 px per side at most) as a public address, a base64 data URI, or a file sent with POST as multipart/form-data.",
"details": {
"field": "image"
}
}
} A title or a component takes no image
{
"error": {
"code": "image_not_supported",
"message": "Titles and components do not take an image.",
"details": {
"field": "image"
}
}
} Element blocked by moderation
{
"error": {
"code": "element_blocked",
"message": "This element is blocked by moderation and can no longer be modified."
}
} More than 120 requests within the minute
{
"error": {
"code": "rate_limited",
"message": "Too many requests: 120 per minute per token."
}
} Remove a link's image
DELETE/v1/pages/{id}/links/{lien}/image
Deletes the link's image; the response is the link. Nothing else is deleted: the Write scope is enough.
curl -X DELETE https://api.tinylink.fr/v1/pages/P6ad34a0e4fef09/links/L6ad34a0e84122/image \
-H "Authorization: Bearer tl_your_token"
const response = await fetch('https://api.tinylink.fr/v1/pages/P6ad34a0e4fef09/links/L6ad34a0e84122/image', {
method: 'DELETE',
headers: { Authorization: 'Bearer tl_your_token' },
});
const data = await response.json();
$ch = curl_init('https://api.tinylink.fr/v1/pages/P6ad34a0e4fef09/links/L6ad34a0e84122/image');
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'DELETE',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => ['Authorization: Bearer tl_your_token'],
]);
$data = json_decode(curl_exec($ch), true);
curl_close($ch);
import requests
response = requests.delete(
'https://api.tinylink.fr/v1/pages/P6ad34a0e4fef09/links/L6ad34a0e84122/image',
headers={'Authorization': 'Bearer tl_your_token'},
)
data = response.json()
Possible responses
{
"id": "L6ad34a0e84122",
"title": "Mon site",
"description": "",
"url": "https://exemple.fr",
"type": "url",
"format": "LIST",
"size": "FULL",
"visible": true,
"archived": false,
"position": 1,
"status": "active",
"image": null,
"created_at": "2026-10-17T12:12:30+02:00"
} No token in the request
{
"error": {
"code": "missing_token",
"message": "Send your token in the header: Authorization: Bearer tl_…"
}
} Unknown or revoked token
{
"error": {
"code": "invalid_token",
"message": "This token does not exist or has been revoked."
}
} The owner's plan does not include the API
{
"error": {
"code": "plan_required",
"message": "The TinyLink API is included in the Pro and Business plans. Upgrade the plan of this environment's owner to use it."
}
} The token does not carry the Write scope
{
"error": {
"code": "insufficient_scope",
"message": "This token does not have the \"write\" scope.",
"details": {
"required_scope": "write"
}
}
} No page with this id or slug in the environment
{
"error": {
"code": "not_found",
"message": "Page not found in this environment."
}
} No link with this id on the page
{
"error": {
"code": "not_found",
"message": "Link not found on this page."
}
} A title or a component takes no image
{
"error": {
"code": "image_not_supported",
"message": "Titles and components do not take an image.",
"details": {
"field": "image"
}
}
} Element blocked by moderation
{
"error": {
"code": "element_blocked",
"message": "This element is blocked by moderation and can no longer be modified."
}
} More than 120 requests within the minute
{
"error": {
"code": "rate_limited",
"message": "Too many requests: 120 per minute per token."
}
}