Documentación

Guía de la API de SULI

Conecta SULI con tu propio código — tu CRM, tu app o tus scripts de automatización — para crear y consultar enlaces cortos sin que nadie tenga que entrar al panel a mano.

Cada organización es un compartimento aislado: la clave que generes solo puede ver y crear enlaces de tu organización, nunca de otra.

Primeros pasos

1
Inicia sesión en SULI con un usuario que tenga rol administrador.
2
Ve a API en el menú superior (o entra directo a /api-keys.php).
3
Escribe un nombre para identificar la clave (ej. "Integración CRM", "Script de marketing") y presiona Generar clave.
4
Copia la clave inmediatamente. Por seguridad, solo se muestra una vez — ni siquiera un administrador puede volver a verla completa después. Si la pierdes, genera una nueva y revoca la anterior.
5
Guarda la clave en un lugar seguro (variable de entorno, gestor de secretos), nunca en código fuente que se suba a un repositorio público.
6
Prueba que funciona con este comando (cambia TU_API_KEY por tu clave real):
curl https://url.51x.mx/api/links -H "Authorization: Bearer TU_API_KEY"

Si todo está bien, verás una respuesta JSON con tus enlaces (o una lista vacía si aún no tienes ninguno).

Autenticación

Cada llamada a la API debe incluir un header Authorization con el formato:

Authorization: Bearer suli_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

No hay usuario/contraseña ni cookies de sesión — la clave por sí sola identifica tanto tu organización como el rol con el que operas.

Revocar una clave: desde /api-keys.php, botón "Revocar". Efecto inmediato — cualquier integración que la use empezará a recibir 401 invalid_api_key.

Permisos según el rol

Cuando generas una clave, esta hereda el rol del usuario que la creó. Si ese usuario cambia de rol o se desactiva su organización, la clave se ajusta automáticamente (no hace falta regenerarla).

Rol del usuario que generó la clavePuede listar/consultar (GET)Puede crear (POST)
consultar✅❌
auxiliar❌✅
supervisor✅✅
administrador✅✅

Si tu clave no tiene el permiso necesario, la API responde 403 forbidden — en ese caso, pide a un administrador que te genere una clave desde un usuario con el rol adecuado (normalmente supervisor o administrador cubre la mayoría de los casos de uso).

Base URL

https://url.51x.mx/api/

Todas las rutas de esta guía son relativas a esa base.

Endpoints

Crear un enlace

POST /api/links

CampoTipoObligatorioDescripción
urlstringSíLa URL de destino a la que redirigirá el enlace corto. Debe ser una URL válida (con http:// o https://)
titlestringNoNombre descriptivo, útil para identificar el enlace en el panel
vigenciastringNoCuánto tiempo estará activo el enlace antes de expirar. Vacío (por defecto) = nunca expira. Valores válidos: "", "1m", "6m", "1y", "2y"
custom_codestringNoEl código corto que quieres usar (ej. "promo2026"). Entre 3 y 30 caracteres, solo letras y números. Si no lo envías, SULI genera uno aleatorio de 5 caracteres
cURL
curl -X POST https://url.51x.mx/api/links \
  -H "Authorization: Bearer suli_xxxxxxxx" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://ejemplo.com/pagina-larga",
    "title": "Campaña de agosto",
    "vigencia": "1m"
  }'
PHP
<?php
$ch = curl_init('https://url.51x.mx/api/links');
curl_setopt_array($ch, [
    CURLOPT_POST => true,
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => [
        'Authorization: Bearer suli_xxxxxxxx',
        'Content-Type: application/json',
    ],
    CURLOPT_POSTFIELDS => json_encode([
        'url' => 'https://ejemplo.com/pagina-larga',
        'title' => 'Campaña de agosto',
        'vigencia' => '1m',
    ]),
]);
$response = json_decode(curl_exec($ch), true);
echo $response['data']['short_url'];
JavaScript (fetch)
const res = await fetch('https://url.51x.mx/api/links', {
  method: 'POST',
  headers: {
    'Authorization': 'Bearer suli_xxxxxxxx',
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    url: 'https://ejemplo.com/pagina-larga',
    title: 'Campaña de agosto',
    vigencia: '1m',
  }),
});
const { data } = await res.json();
console.log(data.short_url);
Respuesta exitosa · 201 Created
{
  "data": {
    "id": 42,
    "code": "aB3k9",
    "short_url": "https://url.51x.mx/aB3k9",
    "original_url": "https://ejemplo.com/pagina-larga",
    "title": "Campaña de agosto",
    "expires_at": "2026-09-10 00:00:00",
    "clicks": 0
  }
}

expires_at viene en null si el enlace no tiene vigencia (es indefinido).

Listar enlaces

GET /api/links

Devuelve los enlaces de tu organización, del más reciente al más antiguo.

ParámetroDescripción
pageNúmero de página, empezando en 1 (por defecto: 1)
per_pageResultados por página, máximo 100 (por defecto: 20)
cURL
curl "https://url.51x.mx/api/links?page=1&per_page=50" \
  -H "Authorization: Bearer suli_xxxxxxxx"
Respuesta · 200 OK
{
  "data": [
    {
      "id": 42,
      "code": "aB3k9",
      "short_url": "https://url.51x.mx/aB3k9",
      "original_url": "https://ejemplo.com/pagina-larga",
      "title": "Campaña de agosto",
      "expires_at": "2026-09-10 00:00:00",
      "clicks": 7
    }
  ],
  "pagination": { "page": 1, "per_page": 50, "total": 1 }
}

pagination.total es el número total de enlaces que tiene tu organización (no solo los de esta página) — úsalo para saber cuántas páginas más pedir.

Consultar un enlace específico

GET /api/links/{code}

Donde {code} es el código corto (lo que va después del dominio, ej. aB3k9).

cURL
curl https://url.51x.mx/api/links/aB3k9 \
  -H "Authorization: Bearer suli_xxxxxxxx"

La respuesta usa el mismo formato que un elemento de la lista anterior. Útil para revisar cuántos clics lleva un enlace específico sin tener que listarlos todos.

Manejo de errores

Cuando algo falla, la API siempre responde con este formato:

{ "error": { "code": "invalid_url", "message": "El campo \"url\" es obligatorio y debe ser una URL válida." } }

code es estable y pensado para que tu programa lo compare directamente (ej. if (error.code === 'code_taken')); message es para mostrar a un humano o depurar.

HTTPcodeCuándo ocurreQué hacer
401missing_api_keyNo enviaste el header AuthorizationAgrega Authorization: Bearer <tu_clave>
401invalid_api_keyLa clave no existe, fue revocada, o su organización está desactivadaGenera una clave nueva desde /api-keys.php
403forbiddenLa clave no tiene permiso para esta acciónUsa una clave generada por un usuario con más permisos
404not_foundLa ruta no existe, o el {code} consultado no corresponde a ningún enlaceRevisa la URL y el código
409code_takenEl custom_code que enviaste ya lo usa otro enlaceElige otro código o no envíes custom_code
422invalid_url / invalid_vigencia / invalid_custom_codeAlgún campo del cuerpo de la petición no es válidoRevisa error.message para saber exactamente qué corregir
500insert_failedError interno al guardar en la base de datosReintenta; si persiste, contacta al administrador del sistema

Preguntas frecuentes

¿Hay límite de peticiones (rate limit)?

No por ahora. Aun así, evita crear enlaces en bucles sin control — si necesitas crear muchos, agrega una pequeña pausa entre peticiones.

¿Los códigos distinguen mayúsculas de minúsculas?

Sí. abc123 y ABC123 son enlaces distintos.

¿Qué pasa si un enlace vence (vigencia cumplida)?

Deja de redirigir — quien lo visite ve una página de "enlace expirado". El enlace sigue existiendo y apareciendo en GET /api/links, solo que ya no funciona. Por ahora la API no permite eliminarlos ni editarlos; eso se hace desde el panel web.

¿El campo clicks se actualiza al consultar por la API?

No. Solo se incrementa cuando alguien visita el enlace corto real (url.51x.mx/codigo), no cuando lo consultas por GET /api/links/{code}.

¿Puedo tener varias claves activas a la vez?

Sí, no hay límite. Es buena práctica generar una clave distinta por cada integración (una para el CRM, otra para el script de marketing, etc.) para poder revocarlas por separado si una se ve comprometida.