Documentación de la API
Crea y gestiona tus enlaces cortos desde tus propias herramientas. Todas las solicitudes y respuestas están en formato JSON.
Obtener una clave
Inicia sesión, abre Ajustes › Claves de API, ponle un nombre a tu clave y cópiala: solo se muestra una vez. Puedes tener 5 como máximo.
La clave se transmite en el encabezado Authorization de cada solicitud.
Primeros pasos
Todas las solicitudes pasan por la URL base https://shortit.fr/api/v1, mediante HTTPS. Los cuerpos de las solicitudes se envían en JSON con el encabezado Content-Type: application/json y el encabezado Content-Length (curl los añade solo). Los campos están en snake_case y las fechas en formato ISO 8601 en UTC.
Versión 1. En la versión 1, un campo nunca se elimina, se renombra ni cambia de tipo; pueden añadirse campos, así que ignora los que no conozcas. Un cambio incompatible tendría una dirección nueva (/api/v2) y la versión 1 seguiría disponible. Una solicitud que contenga un campo desconocido se rechaza (400): es intencionado, para que un error tipográfico no pase inadvertido.
La especificación OpenAPI, generada a partir del código, es pública: /api/v1/openapi.json. Nunca se devuelve ni se conserva ninguna dirección IP.
Comprueba que tu clave funciona y devuelve la cuenta asociada: su dirección, el número de enlaces y el límite.
curl https://shortit.fr/api/v1/me \
-H "Authorization: Bearer VOTRE_CLE"{
"email": "camille@example.com",
"links": 6,
"links_limit": 1000
}Autenticación
Cada solicitud debe llevar tu clave en el encabezado Authorization, precedida de « Bearer ». Una clave revocada, mal formada o ausente devuelve un error 401. Una clave nunca se transmite en la dirección, y la API no lee ninguna cookie.
Las claves se crean en Ajustes (5 como máximo). Una clave se muestra una sola vez, al crearla: solo se conserva su huella. No caduca: sirve hasta que se revoca, y la revocación es inmediata. Las claves empiezan por shortit_.
Nunca pongas una clave en código público ni en el lado del navegador: úsala desde un servidor o un script. La API no envía encabezados CORS. La cuenta debe tener una dirección verificada y no estar suspendida.
Ejemplo de encabezado de autenticación y de respuesta cuando la clave falta o está revocada.
curl https://shortit.fr/api/v1/links \
-H "Authorization: Bearer shortit_…"{
"error": {
"code": "unauthorized",
"message": "Clé absente ou révoquée."
}
}Crear un enlace
Campos del cuerpo: destination (obligatorio, http o https, 2 048 caracteres como máximo); alias (de 3 a 32 letras, números o guiones, se genera si se omite); title (120 caracteres como máximo); expires_at (fecha ISO 8601 en el futuro); password (de 6 a 128 caracteres, nunca se devuelve: la respuesta solo indica has_password); domain (uno de tus dominios personalizados activos, consulta Mis dominios; si falta: shortit.fr).
Los destinos se controlan igual que en la interfaz: se rechazan las direcciones privadas, las direcciones IP directas, otros acortadores y los sitios señalados como peligrosos (422). Los límites de creación son los mismos que en la interfaz: 10 por hora y 50 por día, y después 429.
Oferta Pro: max_clicks (de 1 a 10 000 000) limita el número de clics; una vez alcanzado el límite, el enlace responde como un enlace caducado. La respuesta indica max_clicks y remaining_clicks (null sin límite). Una cuenta gratuita que envía max_clicks recibe 403 pro_required.
Crea un enlace corto. Solo destination es obligatorio; alias se genera si lo omites.
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": []
}Leer un enlace
Un enlace se identifica por su alias, sin distinguir mayúsculas de minúsculas. Dos dominios pueden tener el mismo alias: para un enlace de uno de tus dominios personalizados, añade el parámetro domain (por ejemplo ?domain=go.monsite.fr) para leerlo, modificarlo, eliminarlo u obtener sus estadísticas; sin él, se trata del enlace de shortit.fr. Un enlace de otra cuenta y un enlace inexistente reciben la misma respuesta: 404 not_found.
Devuelve un enlace de tu cuenta a partir de su 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": []
}Listar mis enlaces
Del más reciente al más antiguo, mediante cursor: mientras next no sea null, pasa su valor en el parámetro cursor para obtener la página siguiente. El cursor es opaco; sigue siendo válido aunque se creen o eliminen enlaces entre dos páginas. Parámetros: limit (de 1 a 100, 20 por defecto), cursor, status (active, disabled, expired o flagged).
Lista tus enlaces. Filtra por estado con 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
}Modificar
Campos modificables: destination, title (null lo borra), expires_at (null lo quita), password (un texto lo cambia, null lo quita) y status (active o disabled). Solo cambian los campos enviados. El alias nunca cambia. Un enlace señalado no se puede modificar (409 link_flagged) y un enlace desactivado por motivos de seguridad no se reactiva (409 link_locked).
Oferta Pro: max_clicks establece o cambia el límite de clics, y su contador vuelve entonces a cero (subir el límite de un enlace que lo había alcanzado lo pone de nuevo en servicio); null elimina el límite.
Plan Pro: las reglas de redirección (5 como máximo) se leen con GET /api/v1/links/ALIAS/rules y se reemplazan con PUT en la misma dirección, con el cuerpo {"rules":[{"type":"country","value":"FR","destination":"https://…"}]}. type es country (código de país ISO, « FR ») o device (mobile, tablet o desktop); gana la primera regla que coincida con el visitante; si no, se usa el destino del enlace. Cada destino se comprueba como el del propio enlace (422). En un enlace con 100 clics o más, el cambio se hace desde el panel (403 confirmation_required).
Modifica el destino, el título, la fecha de caducidad, la contraseña o el estado de un enlace.
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": []
}Eliminar
Elimina un enlace de forma definitiva. La dirección corta deja de funcionar, y un alias que ya se ha usado nunca se reasigna.
curl -X DELETE https://shortit.fr/api/v1/links/atelier26 \
-H "Authorization: Bearer VOTRE_CLE"(cuerpo vacío)Estadísticas de un enlace
Los últimos 30 días (días de Europe/Paris, del más antiguo a hoy) y el total desde la creación. unique_visitors es la suma de los visitantes únicos de cada día: un visitante que vuelve tres días cuenta tres veces (no se conserva ningún identificador duradero). variation_pct compara con el período anterior y vale null cuando este no existe.
Cada desglose (countries, referrers, devices, browsers) se ordena por clics descendentes y se limita a 5 filas. value es el código de país, el dominio de origen, el dispositivo o el navegador; null significa « desconocido » o, con other en true, « otros » (los valores menos frecuentes, agrupados).
Clics, visitantes únicos (contados por día), curva de los últimos 30 días y desgloses.
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
}
]
}Mis dominios
Estado de cada dominio: pending_dns (a la espera de tus registros DNS), verified (propiedad verificada), cert_pending (certificado en curso), active (el dominio redirige), error (la verificación ha fallado o se ha detenido), disabled (desactivado: ha desaparecido un registro, o decisión del administrador).
Lista tus dominios personalizados y su estado de verificación.
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"
}
]
}Límites y errores
Cada clave está limitada a 30 solicitudes por minuto (300 con la oferta Pro, próximamente). Pasado ese límite, la API responde 429 con el encabezado Retry-After, que indica en segundos el plazo antes del próximo intento. Treinta claves rechazadas en un minuto desde una misma dirección hacen que esa dirección sea rechazada durante el resto del minuto.
Todo error tiene el mismo cuerpo: { "error": { "code", "message" } }, con además field y reason para un rechazo de validación (422). El código es estable; el mensaje está pensado para una persona y puede cambiar. Códigos:
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.
Ejemplo de respuesta cuando se supera el límite.
{
"error": {
"code": "rate_limited",
"message": "Trop de requêtes. Réessayez dans 12 secondes."
}
}Ejemplo de rechazo de validación: field y reason indican qué campo y por qué.
{
"error": {
"code": "validation_failed",
"message": "Déjà pris, choisissez-en un autre.",
"field": "alias",
"reason": "taken"
}
}