Documentation de l’API
Créez et gérez vos liens courts depuis vos propres outils. Toutes les requêtes et réponses sont au format JSON.
Obtenir une clé
Connectez-vous, ouvrez Paramètres › Clés d’API, donnez un nom à votre clé puis copiez-la : elle n’est affichée qu’une seule fois. Vous pouvez en avoir 5 au maximum.
La clé se transmet dans l’en-tête Authorization de chaque requête.
Démarrer
Toutes les requêtes passent par l’URL de base https://shortit.fr/api/v1, en HTTPS. Les corps de requête sont envoyés en JSON avec l’en-tête Content-Type: application/json et l’en-tête Content-Length (curl les pose seul). Les champs sont en snake_case, les dates au format ISO 8601 en UTC.
Version 1. Dans la version 1, un champ n’est jamais retiré, renommé ni changé de type ; des champs peuvent être ajoutés, donc ignorez ceux que vous ne connaissez pas. Un changement incompatible aurait une nouvelle adresse (/api/v2) et la version 1 resterait disponible. Une requête qui contient un champ inconnu est refusée (400) : c’est voulu, pour qu’une faute de frappe ne passe pas inaperçue.
La spécification OpenAPI, générée depuis le code, est publique : /api/v1/openapi.json. Aucune adresse IP n’est jamais renvoyée ni conservée.
Vérifie que votre clé fonctionne et renvoie le compte associé : son adresse, le nombre de liens et le plafond.
curl https://shortit.fr/api/v1/me \
-H "Authorization: Bearer VOTRE_CLE"{
"email": "camille@example.com",
"links": 6,
"links_limit": 1000
}Authentification
Chaque requête doit porter votre clé dans l’en-tête Authorization, précédée de « Bearer ». Une clé révoquée, mal formée ou absente renvoie une erreur 401. Une clé ne se transmet jamais dans l’adresse, et l’API ne lit aucun cookie.
Les clés se créent dans Paramètres (5 au maximum). Une clé est affichée une seule fois, à sa création : seule son empreinte est conservée. Elle n’expire pas : elle sert jusqu’à sa révocation, qui est immédiate. Les clés commencent par shortit_.
Ne mettez jamais une clé dans du code public ou côté navigateur : utilisez-la depuis un serveur ou un script. L’API n’envoie pas d’en-têtes CORS. Le compte doit avoir une adresse vérifiée et ne pas être suspendu.
Exemple d’en-tête d’authentification, et de réponse quand la clé est absente ou révoquée.
curl https://shortit.fr/api/v1/links \
-H "Authorization: Bearer shortit_…"{
"error": {
"code": "unauthorized",
"message": "Clé absente ou révoquée."
}
}Créer un lien
Champs du corps : destination (obligatoire, http ou https, 2 048 caractères au plus) ; alias (3 à 32 lettres, chiffres ou tirets, généré si omis) ; title (120 caractères au plus) ; expires_at (date ISO 8601 dans le futur) ; password (6 à 128 caractères, jamais renvoyé : la réponse indique seulement has_password) ; domain (l’un de vos domaines personnalisés actifs, voir Mes domaines ; absent : shortit.fr).
Les destinations sont contrôlées comme dans l’interface : adresses privées, adresses IP brutes, autres réducteurs et sites signalés comme dangereux sont refusés (422). Les limites de création sont les mêmes que dans l’interface : 10 par heure et 50 par jour, puis 429.
Offre Pro : max_clicks (1 à 10 000 000) limite le nombre de clics ; une fois la limite atteinte, le lien répond comme un lien expiré. La réponse indique max_clicks et remaining_clicks (null sans limite). Un compte gratuit qui envoie max_clicks reçoit 403 pro_required.
Crée un lien court. Seul destination est obligatoire ; alias est généré si vous l’omettez.
curl -X POST https://shortit.fr/api/v1/links \
-H "Authorization: Bearer VOTRE_CLE" \
-H "Content-Type: application/json" \
-d '{"destination":"https://exemple-atelier.fr/inscriptions/printemps-2026","alias":"atelier26","title":"Atelier printemps"}'{
"alias": "atelier26",
"domain": "shortit.fr",
"short_url": "https://shortit.fr/atelier26",
"destination": "https://exemple-atelier.fr/inscriptions/printemps-2026",
"title": "Atelier printemps",
"status": "active",
"expires_at": null,
"has_password": false,
"created_at": "2026-09-14T09:12:00.000Z",
"max_clicks": null,
"remaining_clicks": null,
"tags": []
}Lire un lien
Un lien se désigne par son alias, sans tenir compte de la casse. Deux domaines peuvent porter le même alias : pour un lien sur l’un de vos domaines personnalisés, ajoutez le paramètre domain (par exemple ?domain=go.monsite.fr) à lire, modifier, supprimer ou obtenir les statistiques ; sans lui, c’est le lien de shortit.fr. Un lien d’un autre compte et un lien inexistant reçoivent la même réponse : 404 not_found.
Renvoie un lien de votre compte à partir de son alias.
curl https://shortit.fr/api/v1/links/atelier26 \
-H "Authorization: Bearer VOTRE_CLE"{
"alias": "atelier26",
"domain": "shortit.fr",
"short_url": "https://shortit.fr/atelier26",
"destination": "https://exemple-atelier.fr/inscriptions/printemps-2026",
"title": "Atelier printemps",
"status": "active",
"expires_at": null,
"has_password": false,
"created_at": "2026-09-14T09:12:00.000Z",
"max_clicks": null,
"remaining_clicks": null,
"tags": []
}Lister mes liens
Du plus récent au plus ancien, par curseur : tant que next n’est pas null, passez sa valeur dans le paramètre cursor pour obtenir la page suivante. Le curseur est opaque ; il reste valable même si des liens sont créés ou supprimés entre deux pages. Paramètres : limit (1 à 100, 20 par défaut), cursor, status (active, disabled, expired ou flagged).
Liste vos liens. Filtrez par état avec status.
curl "https://shortit.fr/api/v1/links?status=active&limit=20" \
-H "Authorization: Bearer VOTRE_CLE"{
"data": [
{
"alias": "atelier26",
"domain": "shortit.fr",
"short_url": "https://shortit.fr/atelier26",
"destination": "https://exemple-atelier.fr/inscriptions/printemps-2026",
"title": "Atelier printemps",
"status": "active",
"expires_at": null,
"has_password": false,
"created_at": "2026-09-14T09:12:00.000Z",
"max_clicks": null,
"remaining_clicks": null,
"tags": []
}
],
"next": null
}Modifier
Champs modifiables : destination, title (null l’efface), expires_at (null le retire), password (un texte le change, null le retire) et status (active ou disabled). Seuls les champs envoyés changent. L’alias ne change jamais. Un lien signalé ne se modifie pas (409 link_flagged) et un lien désactivé pour un motif de sécurité ne se réactive pas (409 link_locked).
Offre Pro : max_clicks pose ou change la limite de clics, et son compteur repart alors de zéro (relever la limite d’un lien qui l’a atteinte le remet en service) ; null retire la limite.
Offre Pro : les règles de redirection (5 au plus) se lisent avec GET /api/v1/links/ALIAS/rules et se remplacent avec PUT sur la même adresse, avec le corps {"rules":[{"type":"country","value":"FR","destination":"https://…"}]}. type vaut country (code pays ISO, « FR ») ou device (mobile, tablet ou desktop) ; la première règle qui correspond au visiteur gagne, sinon la destination du lien. Chaque destination est contrôlée comme celle du lien (422). Sur un lien de 100 clics ou plus, la modification se fait depuis le tableau de bord (403 confirmation_required).
Modifie la destination, le titre, l’échéance, le mot de passe ou l’état d’un lien.
curl -X PATCH https://shortit.fr/api/v1/links/atelier26 \
-H "Authorization: Bearer VOTRE_CLE" \
-H "Content-Type: application/json" \
-d '{"status":"disabled"}'{
"alias": "atelier26",
"domain": "shortit.fr",
"short_url": "https://shortit.fr/atelier26",
"destination": "https://exemple-atelier.fr/inscriptions/printemps-2026",
"title": "Atelier printemps",
"status": "disabled",
"expires_at": null,
"has_password": false,
"created_at": "2026-09-14T09:12:00.000Z",
"max_clicks": null,
"remaining_clicks": null,
"tags": []
}Supprimer
Supprime définitivement un lien. L’adresse courte cesse de fonctionner, et un alias qui a déjà servi n’est jamais réattribué.
curl -X DELETE https://shortit.fr/api/v1/links/atelier26 \
-H "Authorization: Bearer VOTRE_CLE"(corps vide)Statistiques d’un lien
Les 30 derniers jours (jours d’Europe/Paris, du plus ancien à aujourd’hui) et le total depuis la création. unique_visitors est la somme des visiteurs uniques de chaque jour : un visiteur revenu trois jours compte trois fois (aucun identifiant durable n’est conservé). variation_pct compare à la période précédente et vaut null quand elle n’existe pas.
Chaque répartition (countries, referrers, devices, browsers) est triée par clics décroissants et limitée à 5 lignes. value est le code pays, le domaine d’origine, l’appareil ou le navigateur ; null veut dire « inconnu », ou, avec other à true, « autres » (les valeurs les moins fréquentes, regroupées).
Clics, visiteurs uniques (comptés par jour), courbe des 30 derniers jours et répartitions.
curl https://shortit.fr/api/v1/links/atelier26/stats \
-H "Authorization: Bearer VOTRE_CLE"{
"alias": "atelier26",
"period_days": 30,
"clicks": 1397,
"unique_visitors": 1006,
"total_clicks": 2310,
"variation_pct": 12.4,
"days": [
{
"date": "2026-09-12",
"clicks": 61
},
{
"date": "2026-09-13",
"clicks": 48
}
],
"countries": [
{
"value": "FR",
"clicks": 925
},
{
"value": "BE",
"clicks": 201
},
{
"value": null,
"clicks": 271,
"other": true
}
],
"referrers": [
{
"value": "instagram.com",
"clicks": 512
},
{
"value": null,
"clicks": 885
}
],
"devices": [
{
"value": "mobile",
"clicks": 944
},
{
"value": "desktop",
"clicks": 453
}
],
"browsers": [
{
"value": "Safari",
"clicks": 601
},
{
"value": "Chrome",
"clicks": 796
}
]
}Mes domaines
État de chaque domaine : pending_dns (en attente de vos enregistrements DNS), verified (propriété vérifiée), cert_pending (certificat en cours), active (le domaine redirige), error (la vérification a échoué ou s’est arrêtée), disabled (désactivé : un enregistrement a disparu, ou décision de l’administrateur).
Liste vos domaines personnalisés et leur état de vérification.
curl https://shortit.fr/api/v1/domains \
-H "Authorization: Bearer VOTRE_CLE"{
"data": [
{
"name": "go.camille.fr",
"status": "active",
"created_at": "2026-09-02T08:00:00.000Z"
},
{
"name": "liens.exemple-asso.fr",
"status": "pending_dns",
"created_at": "2026-09-14T09:12:00.000Z"
}
]
}Limites et erreurs
Chaque clé est limitée à 30 requêtes par minute (300 avec l’offre Pro, à venir). Au-delà, l’API répond 429 avec l’en-tête Retry-After, qui indique en secondes le délai avant le prochain essai. Trente clés refusées en une minute depuis une même adresse font refuser cette adresse pendant le reste de la minute.
Toute erreur a le même corps : { "error": { "code", "message" } }, avec en plus field et reason pour un refus de validation (422). Le code est stable ; le message est destiné à une personne et peut changer. Codes :
unauthorized (401) : Clé absente, mal formée ou révoquée.
email_not_verified (403) : L'adresse e-mail du compte n'est pas vérifiée.
account_suspended (403) : Le compte est suspendu.
link_limit_reached (403) : Le plafond de liens du compte est atteint.
pro_required (403) : Cette fonction (limite de clics, règles de redirection…) est réservée aux comptes de l'offre Pro.
confirmation_required (403) : Ce lien a beaucoup de clics : changer sa destination ou ses règles de redirection, ou le supprimer, se fait depuis le tableau de bord, avec un code reçu par e-mail.
not_found (404) : Lien introuvable, ou qui n'est pas à vous.
link_flagged (409) : Le lien est signalé : il ne se modifie ni ne se supprime.
link_locked (409) : Le lien a été désactivé pour un motif de sécurité : il ne se réactive pas.
invalid_json (400) : Le corps n'est pas du JSON valide.
invalid_request (400) : Requête invalide : champ inconnu, type inattendu ou paramètre hors limites.
validation_failed (422) : Une valeur est refusée : le corps porte field et reason.
payload_too_large (413) : Corps de plus de 16 Ko.
length_required (411) : L'en-tête Content-Length est obligatoire avec un corps.
unsupported_media_type (415) : Content-Type : application/json obligatoire avec un corps.
rate_limited (429) : Plus de requêtes par minute que l'offre ne le permet (30 en gratuit, 300 en Pro) avec cette clé : voir Retry-After.
internal_error (500) : Erreur du serveur. Réessayez ; elle ne détaille rien.
Exemple de réponse lorsque la limite est dépassée.
{
"error": {
"code": "rate_limited",
"message": "Trop de requêtes. Réessayez dans 12 secondes."
}
}Exemple de refus de validation : field et reason disent quel champ et pourquoi.
{
"error": {
"code": "validation_failed",
"message": "Déjà pris, choisissez-en un autre.",
"field": "alias",
"reason": "taken"
}
}