chu.es

API del acortador de enlaces

Crea enlaces cortos de chu.es, cámbialos y consulta sus estadísticas desde tu web, tu tienda o tus scripts. API REST con respuestas en JSON y gratuita.

Primeros pasos

  1. Crea una cuenta gratis en chu.es (o entra con Google).
  2. En Mis enlaces → API, pulsa «Crear clave de API» y guárdala: solo se muestra una vez.
  3. Haz tu primera llamada:
curl -X POST https://chu.es/api/v1/links \
  -H "Authorization: Bearer TU_CLAVE" \
  -H "Content-Type: application/json" \
  -d '{"url": "https://www.ejemplo.com/una/direccion/larga"}'

Respuesta (201 Created):

{
    "data": {
        "code": "k7mq2x",
        "short_url": "https://chu.es/k7mq2x",
        "url": "https://www.ejemplo.com/una/direccion/larga",
        "title": null,
        "active": true,
        "status": "active",
        "clicks": 0,
        "created_at": "2026-10-11T23:50:00+02:00",
        "last_click_at": null
    },
    "existing": false
}

Autenticación

Todas las peticiones llevan tu clave en la cabecera Authorization:

Authorization: Bearer chu_1a2b3c4d_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

También se acepta la cabecera X-API-Key. La URL base es https://chu.es/api/v1. Los cuerpos se envían en JSON (Content-Type: application/json) o como formulario. Trata la clave como una contraseña: no la pongas en código que se ejecute en el navegador de tus visitantes. Puedes revocarla y crear otra en cualquier momento desde el panel.

POST/links

Crea un enlace corto.

CampoTipoDescripción
urltexto, obligatorioDirección de destino (http o https, máximo 2048 caracteres). Si no lleva esquema se entiende https.
aliastexto, opcionalNombre del enlace: chu.es/mi-oferta. De 3 a 50 caracteres: letras sin tilde, números y guiones. No distingue mayúsculas.
titletexto, opcionalTítulo interno para reconocerlo en el panel (máximo 200 caracteres).

Si ya habías acortado la misma dirección sin alias, se devuelve ese enlace con 200 y "existing": true en lugar de crear otro.

GET/links

Tus enlaces, del más reciente al más antiguo. Parámetros: page (desde 1), per_page (1–100, por defecto 50) y q (busca en código, destino y título).

curl "https://chu.es/api/v1/links?per_page=20&q=oferta" -H "Authorization: Bearer TU_CLAVE"

Devuelve {"data": [ … ], "page": 1, "per_page": 20, "total": 3}.

GET/links/{code}

Datos de un enlace tuyo. clicks es el total histórico de clics de personas (sin bots).

PATCH/links/{code}

Cambia uno o varios campos: url (nuevo destino), title y active (false lo pausa; true lo reactiva). El código no cambia, así que los QR impresos siguen valiendo.

curl -X PATCH https://chu.es/api/v1/links/mi-oferta \
  -H "Authorization: Bearer TU_CLAVE" -H "Content-Type: application/json" \
  -d '{"url": "https://www.ejemplo.com/nueva-oferta", "active": true}'

DELETE/links/{code}

Borra el enlace y sus estadísticas. Responde 204 sin cuerpo. El código queda retirado para siempre: nadie podrá reutilizarlo.

GET/links/{code}/stats

Estadísticas de los últimos days días (1–400, por defecto 30). Solo cuenta personas: los bots y las vistas previas de redes sociales y apps de mensajería van aparte en bot_hits.

{
    "data": {
        "code": "mi-oferta",
        "days": 30,
        "clicks": 412,
        "unique_visitors": 355,
        "bot_hits": 61,
        "total_clicks": 1290,
        "by_day": [ {"date": "2026-09-12", "clicks": 8}, … ],
        "countries": [ {"code": "ES", "name": "España", "clicks": 380}, … ],
        "referrers": [ {"name": "instagram.com", "clicks": 120}, {"name": "Directo / sin procedencia", "clicks": 98}, … ],
        "devices": [ {"name": "Móvil", "clicks": 301}, … ],
        "browsers": [ {"name": "Chrome", "clicks": 190}, … ],
        "os": [ {"name": "Android", "clicks": 170}, … ]
    }
}

unique_visitors cuenta personas distintas por día (no guardamos IPs: usamos un código anónimo que cambia cada día).

GET/me

Tu cuenta: email, plan y links_left_today (enlaces que aún puedes crear hoy; null = sin límite).

Errores y límites

Los errores responden con el código HTTP adecuado y este formato:

{
    "error": {
        "code": "alias_taken",
        "message": "El alias «mi-oferta» ya está en uso. Elige otro."
    }
}
HTTPcodeCuándo
400invalid_jsonEl cuerpo no es JSON válido.
401unauthorizedFalta la clave o no es válida.
403link_blockedEl enlace está desactivado por incumplir las condiciones de uso.
404not_foundNo existe ningún enlace tuyo con ese código, o la ruta no existe.
409alias_takenEl alias ya está ocupado.
422invalid_url · invalid_alias · blocked_destination · invalid_fieldDirección no válida o inaccesible, alias no válido o reservado, destino en una lista de sitios peligrosos, campo con valor incorrecto.
429rate_limited · quota_exceededMás de 120 peticiones o 60 enlaces nuevos por minuto, o cupo diario agotado (200 enlaces al día en el plan gratuito). Mira la cabecera Retry-After.

No se pueden acortar enlaces de otros acortadores, direcciones IP ni dominios que no resuelven o que figuran en listas de phishing y malware (Spamhaus DBL, SURBL, URIBL). Los enlaces deben cumplir el aviso legal y las condiciones de uso.

Ejemplos

PHP

<?php
$ch = curl_init('https://chu.es/api/v1/links');
curl_setopt_array($ch, [
  CURLOPT_POST => true,
  CURLOPT_RETURNTRANSFER => true,
  CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . getenv('CHU_API_KEY'), 'Content-Type: application/json'],
  CURLOPT_POSTFIELDS => json_encode(['url' => 'https://www.ejemplo.com/producto/123']),
]);
$res = json_decode(curl_exec($ch), true);
echo $res['data']['short_url'];

Python

import os, requests

r = requests.post('https://chu.es/api/v1/links',
                  headers={'Authorization': f"Bearer {os.environ['CHU_API_KEY']}"},
                  json={'url': 'https://www.ejemplo.com/producto/123', 'alias': 'producto-123'})
r.raise_for_status()
print(r.json()['data']['short_url'])

JavaScript (Node.js 18+)

const r = await fetch('https://chu.es/api/v1/links/producto-123/stats?days=7', {
  headers: { Authorization: `Bearer ${process.env.CHU_API_KEY}` },
});
const { data } = await r.json();
console.log(data.clicks, 'clics esta semana');