Nombre
Crear un enlace corto
Publica un enlace corto con código generado o alias propio. Se cobra al crearlo, salvo que tu plan lo incluya.
Método HTTP y ruta
/ api/ v6/ urlshortener/ linkshttps:
Qué pasa al ejecutarlo
- Crea datos en tu organización.
- La llamada se cobra a tu organización.
- Después, cada visita de una persona al enlace también se cobra (las de robots y las vistas previas no).
Qué hace
Crea un enlace corto en uno de los dominios disponibles para tu organización. Si no envías code, el servicio genera uno de 7 caracteres (0-9a-z); si lo envías, queda como alias (isAlias:). Los códigos son únicos por dominio, y el de un enlace eliminado no se puede volver a usar para otro enlace: si era tuyo, puedes restaurarlo durante 90 días.
Cada enlace creado se cobra al precio vigente de tu organización (consúltalo con GET /). Si tu organización tiene un plan mensual del acortador vigente, crear enlaces no se cobra, y entonces rige un cupo diario de altas (100.000 por día de Colombia, salvo que tengas otro pactado): al llegar, la API responde 429 URLSHORTENER_LINK_QUOTA_EXCEEDED hasta la medianoche. Sin plan no hay cupo diario: sin saldo disponible la API responde 402 y el enlace no se crea.
¿Muchos enlaces a la vez, por ejemplo para una campaña? Usa el alta en lote: hasta 1.000 por petición, con las mismas reglas y un solo cobro por lo que se creó.
Disponibilidad y requisitos previos
- Publicado y disponible en la API v6 de producción.
- Todas las rutas parten de
https:./ / developers. hablame. co - Necesitas una API key de Hablame para llamarlo.
Autenticación y permisos
- Envía tu API key en la cabecera
Authorizationcon el esquema Bearer.
Quién puede llamarlo: Una API key con el servicio urlshortener habilitado.
Límites y consideraciones operativas
Límite de uso: 35 solicitudes por segundo.
- La URL de destino admite hasta 2048 caracteres; el cuerpo, hasta 64 KiB.
- Se rechazan destinos en
localhost,*.,local *.o en IP privadas o reservadas; destinos que ya son un enlace corto (nuestros dominios o acortadores como bit.ly, tinyurl.com o t.co); destinos con usuario o clave antes del dominio (internal usuario@); dominios con tildes, eñes u otros alfabetos (también enxn--), y URL con caracteres invisibles. - Con plan: hasta 100.000 altas por día de Colombia (cupo diario).
Parámetros de ruta
Este endpoint no tiene parámetros de ruta.
Parámetros de consulta
Este endpoint no tiene parámetros de consulta.
Encabezados HTTP
| Nombre | Tipo | Descripción y reglas |
|---|---|---|
AuthorizationObligatorio | string | Tu API key con el esquema Bearer. Ejemplo: |
Content-TypeObligatorio | string | Tipo del cuerpo que envías. Valor fijo: |
Idempotency-KeyOpcional | string | Llave de idempotencia opcional (1 a 255 caracteres de Patrón: |
Cuerpo de la petición
Tipo de contenido:application/jsonObligatorio
Solo se aceptan estos cuatro campos. Uno que no existe (por ejemplo url o alias, del contrato anterior) se rechaza con 400 nombrando el campo.
| Nombre | Tipo | Descripción y reglas |
|---|---|---|
longUrlObligatorio | string | URL de destino. Absoluta Formato: |
domainOpcional | string | Dominio donde publicar, uno de Ejemplo: |
codeOpcional | string | Alias opcional: 3 a 32 caracteres entre minúsculas, dígitos, Patrón: |
expiresAtOpcional | string | Vencimiento opcional, siempre futuro. Acepta RFC 3339 y también Formato: |
{
"longUrl": "https://example.com/landing?utm_source=sms",
"domain": "h0b.co",
"code": "promo-septiembre",
"expiresAt": "2026-12-31T23:59:59-05:00"
}Respuestas satisfactorias
201
Enlace creado. Con Idempotency-Key repetida y el mismo cuerpo, es el enlace de la primera vez (Idempotency-Status:): no se creó otro ni se cobró de nuevo.
{
"success": true,
"data": {
"domain": "h0b.co",
"code": "a1b2c3d",
"shortUrl": "https://h0b.co/a1b2c3d",
"longUrl": "https://example.com/landing?utm_source=sms",
"isAlias": false,
"status": "active",
"domainStatus": "active",
"expiresAt": null,
"createdAt": "2026-09-23T15:04:05Z",
"clicks": 0,
"uniqueClicks": 0,
"firstClickAt": null,
"lastClickAt": null
},
"meta": {
"requestId": "8f0c0e2a4b1d4c8f",
"clientIp": "203.0.113.45",
"timestamp": "2026-09-23T18:30:00+00:00",
"responseTimeMs": 7.2
}
}Los valores del ejemplo son ilustrativos.
Campos de la respuesta
| Nombre | Tipo | Descripción y reglas |
|---|---|---|
successSiempre presente | boolean | |
dataSiempre presente | object | |
data.Siempre presente | string | Dominio del enlace, en minúsculas. Si el dominio ya no es de tu organización ( |
data.Siempre presente | string | Código del enlace, en minúsculas: 7 caracteres |
data.Siempre presente | string | La URL corta completa: siempre Formato: |
data.Siempre presente | string | URL de destino. Formato: |
data.Siempre presente | boolean |
|
data.Siempre presente | string |
Valores permitidos: |
data. | string | Si el dominio deja abrir el enlace, aparte de su propio Valores permitidos: |
data.Siempre presente | string | Vencimiento en UTC, o Puede llegar en Formato: |
data.Siempre presente | string | Fecha de creación, en UTC. Formato: |
data.Siempre presente | integer | Visitas de toda la vida del enlace. Las consolida un proceso en segundo plano: una visita puede tardar de segundos a pocos minutos en reflejarse. No cuenta bots ni las vistas previas que generan las redes sociales y los chats. |
data.Siempre presente | integer | Suma de las visitas únicas de cada día: la primera visita del día desde cada navegador. No son personas distintas en toda la vida del enlace. |
data.Siempre presente | string | Primera visita, en UTC. Puede llegar en Formato: |
data.Siempre presente | string | Última visita, en UTC. Puede llegar en Formato: |
metaSiempre presente | object | Metadatos de la respuesta. |
meta.Siempre presente | string | Identificador único de la solicitud (16 caracteres hexadecimales). Es el mismo de la cabecera Ejemplo: |
meta.Siempre presente | string | IP con la que la API vio tu solicitud. Útil si tu API key solo admite ciertas redes. Ejemplo: |
meta.Siempre presente | string | Fecha y hora en que se construyó la respuesta (ISO 8601 con offset). Formato: |
meta.Siempre presente | number | Tiempo (ms) que tomó procesar la solicitud en el servidor. Ejemplo: |
Códigos de error
Todas las respuestas de error tienen la misma forma: success en false y un objeto error cuyo code dice qué pasó. Aquí están agrupadas por tipo, con los códigos que este endpoint puede devolver.
Forma de una respuesta de error
| Nombre | Tipo | Descripción y reglas |
|---|---|---|
successSiempre presente | boolean | Valor fijo: |
metaSiempre presente | object | Metadatos de la respuesta. |
meta.Siempre presente | string | Identificador único de la solicitud (16 caracteres hexadecimales). Es el mismo de la cabecera Ejemplo: |
meta.Siempre presente | string | IP con la que la API vio tu solicitud. Útil si tu API key solo admite ciertas redes. Ejemplo: |
meta.Siempre presente | string | Fecha y hora en que se construyó la respuesta (ISO 8601 con offset). Formato: |
meta.Siempre presente | number | Tiempo (ms) que tomó procesar la solicitud en el servidor. Ejemplo: |
errorSiempre presente | object | |
error.Siempre presente | string | Identificador estable en UPPER_SNAKE_CASE. Los clientes ramifican sobre este valor. Ejemplo: |
error. | integer | Código numérico legacy v5, solo cuando hay puente. Se omite en los códigos nacidos en v6. Ejemplo: |
error.Siempre presente | string | URL a la documentación del error. Formato: |
error.Siempre presente | string | Texto legible en inglés. Es para el log del desarrollador, no para el usuario final: no lo parsees. |
error.Siempre presente | array<object> | Contexto estructurado (validaciones, recurso afectado). Arreglo vacío cuando no hay contexto extra. |
Validación
- 400Cuerpo inválido: URL de destino, alias, vencimiento o dominio, un campo que no existe, JSON mal formado, o una
Idempotency-Keycon otra forma. - 422La
Idempotency-Keyya se usó para crear un enlace con otro cuerpo. Usa una llave nueva para un enlace nuevo.
400VALIDATION_INVALID_PARAMETER
Un parámetro o un campo del cuerpo no es válido.
La llave de idempotencia no cumple el formato.
La llave ya existe, pero con un cuerpo distinto.
400URL_INVALID
La URL de destino está mal formada.
Mensaje que devuelve la API: The destination URL is not valid. Provide an absolute `http`/`https` URL with a host.
Solo se admiten destinos http y https.
Mensaje que devuelve la API: Only `http` and `https` destination URLs are allowed.
400URL_TOO_LONG
La URL de destino supera el largo máximo.
Mensaje que devuelve la API: The destination URL exceeds the maximum allowed length.
El host de destino es privado o reservado.
Mensaje que devuelve la API: The destination host is not allowed (private, reserved, or loopback addresses are blocked).
El alias no cumple el formato permitido.
Mensaje que devuelve la API: The alias must be 3-32 characters of lowercase letters, digits, hyphen or underscore.
expiresAtdebe ser una fecha ISO futura.Mensaje que devuelve la API: `expiresAt` must be a future ISO-8601 date-time.
El dominio elegido no está disponible para tu cuenta.
Mensaje que devuelve la API: The requested domain is not available for this account.
Autenticación
- 401Credenciales inválidas o faltantes.
No se envió un token Bearer y cada llamada lo requiere.
Mensaje que devuelve la API: Authentication is required. Send your API key as `Authorization: Bearer <token>`.
La clave de API no se reconoce: formato equivocado, revocada o vencida.
Mensaje que devuelve la API: The provided API key is invalid or has expired. Please verify the value sent in the `Authorization: Bearer` header.
Permisos
- 403La API key no tiene habilitado el acortador (o está apagado para tu organización), la key no se puede usar desde la red de la petición, o la organización no está activa.
La clave no tiene permitido el servicio detrás de este endpoint.
Mensaje que devuelve la API: This API key is not authorized to use the requested service.
La clave solo funciona desde ciertas redes y tu IP no está entre ellas.
Mensaje que devuelve la API: This API key cannot be used from this IP address. The address we saw is in `meta.clientIp`: call from one of the networks allowed for the key, or use a key that allows this one.
Tu organización está suspendida o cerrada.
Mensaje que devuelve la API: The organization associated with this API key is not active. Please contact support.
No pudimos cargar la organización de tu clave.
Mensaje que devuelve la API: Organization configuration could not be loaded. Please contact support.
Límites de uso
- 429Se excedió el límite de solicitudes, o (con plan) el cupo diario de altas. En el segundo caso
Retry-Afterdice cuánto falta para la medianoche de Colombia.
429URLSHORTENER_LINK_QUOTA_EXCEEDED
Tu organización llegó al cupo diario de enlaces de su plan.
Excediste el cupo de tu organización para este endpoint.
Mensaje que devuelve la API: You have exceeded the allowed request rate for this endpoint. Please wait before retrying.
Recurso inexistente
Este endpoint no declara respuestas de este tipo.
Errores internos y disponibilidad
- 500No se pudo generar un código libre. Reintenta.
- 503No se pudo comprobar el saldo en este momento. El enlace no se crea; puedes reintentar (mejor con
Idempotency-Key).
Algo salió mal de nuestro lado.
Mensaje que devuelve la API: Internal Server Error
503 genérico: un servicio del que dependemos no responde.
Otras respuestas
- 402Tu organización no tiene saldo disponible para crear el enlace (o no tiene cuenta de facturación activa), o crearlo superaría un tope de gasto que ella misma configuró (
URLSHORTENER_SPEND_LIMIT_REACHED: se ajusta en los topes de gasto, recargar no lo resuelve). El enlace no se crea. - 409El alias ya está en uso en ese dominio, es una palabra reservada o una marca en un dominio compartido, o es el de un enlace tuyo eliminado (
ALIAS_RETIRED: restáuralo); el dominio propio no está verificado; o el acortador no tiene precio para la moneda de tu organización, o tu organización todavía no tiene moneda. En los dos últimos casos no se arregla reintentando.
409ALIAS_TAKEN
El alias ya se usó en este dominio.
Mensaje que devuelve la API: That alias has already been used on this domain and cannot be used again.
El alias es una palabra reservada.
Mensaje que devuelve la API: That alias is reserved and cannot be used.
El alias es de un enlace tuyo que eliminaste.
Tu dominio todavía no está verificado.
402URLSHORTENER_INSUFFICIENT_FUNDS
Tu organización no tiene saldo para crear el enlace.
402URLSHORTENER_SPEND_LIMIT_REACHED
Se alcanzó un tope de gasto que tu organización configuró.
El acortador no tiene precio configurado para tu moneda.
409URLSHORTENER_CURRENCY_UNDEFINED
Tu organización todavía no tiene moneda definida.
Consideraciones especiales
- Admite la cabecera
Idempotency-Key: si una petición se corta y la repites con la misma llave, no se duplica. Los detalles están en la guía de idempotencia.
Reintenta sin duplicar con Idempotency-Key. Si un alta se corta (un timeout, un 5xx) y la repites con la misma llave y el mismo cuerpo, recibes el mismo enlace (201 con Idempotency-Status:) sin crear otro ni cobrarlo dos veces, aunque la primera todavía se esté procesando. La misma llave con otro cuerpo responde 422 IDEMPOTENCY_KEY_REUSED. En este endpoint la llave queda asociada al enlace para siempre. Sin llave, cada reintento crea y cobra otro enlace.
El cuerpo se valida antes de comprobar el saldo: una URL, un alias, un dominio o un vencimiento inválidos responden su error sin tocar tu saldo.
Una key con el acortador también crea y borra
El servicio urlshortener da todo el acortador: con él, la API key lista y consulta enlaces, y también los crea (cada alta se cobra), los edita, los borra y los restaura. No hay keys de solo lectura. Solo el propietario de tu organización crea las keys: si una no debe crear enlaces, no le des este servicio. Sin él, la key recibe 403 AUTH_SERVICE_NOT_ALLOWED.