Enlaces (API v1, eliminada)
Estos endpoints ya no funcionan
Los seis endpoints de la API v1 de abajo fueron sustituidos por la API v2 y ahora responden 410 Gone con el reemplazo en la respuesta. Pasa a la API v2. Las secciones siguientes describen el formato antiguo y se conservan solo para ayudarte a migrar.
A dónde se movió cada endpoint
API v1 (responde 410) | API v2 |
|---|---|
POST /apiv1/link/create | POST https://api.revolink.link/apiv2/links |
PUT /apiv1/link/update | PATCH https://api.revolink.link/apiv2/links/{id} |
DELETE /apiv1/link/delete | DELETE https://api.revolink.link/apiv2/links/{id} |
POST /apiv1/links/bulk-create | POST https://api.revolink.link/apiv2/links/bulk |
GET /apiv1/links/{id}/analytics | GET https://api.revolink.link/apiv2/links/{id}/analytics |
GET /apiv1/links/analytics | GET https://api.revolink.link/apiv2/analytics |
Qué cambia para ti: la clave va en Authorization: Bearer <key> (o X-Api-Key), el espacio de trabajo va en la cabecera X-Workspace-Id y ya no en el cuerpo ni en la consulta, un enlace se identifica por su id en la URL y las respuestas van envueltas en { "data": … }. Consulta la autenticación de la API v2 y Errores.
Endpoints antiguos (referencia para migrar)
| Método | Ruta | Descripción |
|---|---|---|
POST | /link/create | Crear un enlace |
PUT | /link/update | Actualizar un enlace |
DELETE | /link/delete | Eliminar un enlace |
POST | /links/bulk-create | Crear enlaces de forma masiva |
GET | /links/{id}/analytics | Analítica de un enlace |
GET | /links/analytics | Analítica de todos los enlaces |
Objeto de regla
Las reglas definen adónde redirige un enlace. Todo enlace debe tener al menos una regla con isDefault: true: es el destino de respaldo cuando no se cumplen las condiciones de ninguna otra regla.
Las reglas no predeterminadas se evalúan en orden. Gana la primera regla cuyas condiciones se cumplen todas. Si ninguna regla coincide, se usa la regla predeterminada.
Los ID de las reglas los genera automáticamente el servidor: no incluyas id en tu petición.
Restricciones:
- Exactamente una regla por enlace debe tener
isDefault: true - La regla predeterminada es un respaldo puro: no puede tener ninguna condición (
country,city,device,os,browser,timeStart,timeEnd,daysOfWeek). Las condiciones solo se permiten en las reglas no predeterminadas timeStartytimeEnddeben indicarse juntos o omitirse ambos
| Campo | Tipo | Obligatorio | Descripción |
|---|---|---|---|
targetUrl | string | ✅ | URL de destino. Cualquier URL válida, incluidos los deep links (p. ej. youtube://, myapp://) |
isDefault | boolean | ✅ | Exactamente una regla por enlace debe tener true |
country | string[] | — | Códigos de país ISO 3166-1 alpha-2 (p. ej. ["UA", "PL"]). Solo coinciden los visitantes de estos países |
city | string[] | — | Nombres de ciudad (p. ej. ["Kyiv", "Warsaw"]). Requiere indicar country: no se puede usar una ciudad sin país |
device | string[] | — | Tipos de dispositivo. Valores admitidos: "desktop", "mobile", "tablet", "console", "smarttv", "wearable", "embedded" |
os | string[] | — | Sistemas operativos. Valores admitidos: "Windows", "macOS", "Linux", "iOS", "Android" |
browser | string[] | — | Navegadores. Valores admitidos: "Chrome", "Firefox", "Safari", "Edge", "Opera", "Brave" |
timeStart | string | — | Inicio de la franja horaria activa en formato "HH:MM" (p. ej. "09:00") |
timeEnd | string | — | Fin de la franja horaria activa en formato "HH:MM" (p. ej. "18:00") |
daysOfWeek | number[] | — | Días en que la regla está activa. 0 = domingo … 6 = sábado (p. ej. [1,2,3,4,5] para los días laborables) |
Ejemplo completo de regla (todos los campos de condición opcionales):
{
"targetUrl": "https://example.com/ua-mobile",
"isDefault": false,
"country": ["UA", "PL"],
"city": ["Kyiv", "Warsaw"],
"device": ["mobile"],
"os": ["iOS", "Android"],
"browser": ["Chrome", "Safari"],
"timeStart": "09:00",
"timeEnd": "21:00",
"daysOfWeek": [1, 2, 3, 4, 5]
}
Objeto de prueba A/B
Las pruebas A/B reparten el tráfico al azar entre varias URL de destino según los pesos. Cuando abTest.enabled es true, las reglas de enrutamiento se ignoran: cada visitante va a una de las variantes.
| Campo | Tipo | Obligatorio | Descripción |
|---|---|---|---|
enabled | boolean | ✅ | Pon true para activar las pruebas A/B |
variants | Variant[] | ✅ | Lista de variantes. Mínimo 2 cuando está activada |
Campos de la variante:
| Campo | Tipo | Obligatorio | Descripción |
|---|---|---|---|
id | string | ✅ | Identificador único de la variante. Usa cualquier cadena estable (p. ej. una marca de tiempo): el servidor la guarda tal cual para el seguimiento |
name | string | ✅ | Nombre visible (p. ej. "Variant A") |
url | string | ✅ | URL de destino de esta variante |
weight | number | ✅ | Porcentaje del tráfico. Los pesos de todas las variantes deben sumar exactamente 100 |
Ejemplo:
{
"abTest": {
"enabled": true,
"variants": [
{ "id": "1714000000000", "name": "Variant A", "url": "https://example.com/a", "weight": 60 },
{ "id": "1714000000001", "name": "Variant B", "url": "https://example.com/b", "weight": 40 }
]
}
}
Para desactivar las pruebas A/B al actualizar un enlace:
{
"abTest": { "enabled": false, "variants": [] }
}
Objeto de ajustes del QR
Controla el aspecto visual del código QR generado para un enlace.
| Campo | Tipo | Descripción |
|---|---|---|
color | string | Color de primer plano en formato hex. Por defecto: "#000000" |
bgColor | string | Color de fondo en formato hex. Por defecto: "#ffffff" |
useLogo | boolean | Si se incrusta un logotipo en el centro del código QR. Por defecto: false |
logo | string | Imagen del logotipo como data URL (p. ej. "data:image/png;base64,...") o URL. Obligatorio cuando useLogo es true |
Ejemplo:
{
"qrSettings": {
"color": "#1a1a2e",
"bgColor": "#ffffff",
"useLogo": true,
"logo": "https://example.com/logo.png"
}
}
Crear un enlace
POST /link/create
Petición
POST https://api.revolink.link/apiv1/link/create
Content-Type: application/json
X-Api-Key: rvlnk_your_api_key_here
Campos del cuerpo
| Campo | Tipo | Obligatorio | Descripción |
|---|---|---|---|
workspaceId | string | ✅ | ObjectId del espacio de trabajo |
name | string | ✅ | Nombre visible del enlace |
rules | Rule[] | ✅ | Reglas de enrutamiento. Se requiere al menos una regla con isDefault: true |
description | string | — | Descripción interna (no se muestra a los visitantes). Máx. 1000 caracteres |
slug | string | — | Slug de URL personalizado. Se genera automáticamente si se omite. Solo minúsculas, números y guiones. Máx. 100 caracteres |
domain | string | — | Nombre de host del dominio personalizado (p. ej. "go.mycompany.com"). Debe ser un dominio verificado en el espacio de trabajo. Por defecto rvlnk.link |
active | boolean | — | Por defecto: true |
clicksLimit | number | — | Entero positivo. Sin límite si se omite |
expirationDate | string | — | Fecha y hora ISO 8601. Debe ser futura |
tagIds | string[] | — | Array de ObjectId de etiquetas |
abTest | object | — | Configuración de la prueba A/B. Consulta Objeto de prueba A/B |
qrSettings | object | — | Aspecto del código QR. Consulta Objeto de ajustes del QR |
Ejemplo mínimo
curl -X POST https://api.revolink.link/apiv1/link/create \
-H "Content-Type: application/json" \
-H "X-Api-Key: rvlnk_your_api_key_here" \
-d '{
"workspaceId": "664abc000000000000000001",
"name": "My link",
"rules": [
{
"targetUrl": "https://example.com",
"isDefault": true
}
]
}'
Ejemplo completo (todos los campos)
curl -X POST https://api.revolink.link/apiv1/link/create \
-H "Content-Type: application/json" \
-H "X-Api-Key: rvlnk_your_api_key_here" \
-d '{
"workspaceId": "664abc000000000000000001",
"name": "Summer campaign",
"description": "Main landing for summer 2025 promo",
"slug": "summer-2025",
"domain": "go.mycompany.com",
"active": true,
"clicksLimit": 10000,
"expirationDate": "2025-09-01T00:00:00Z",
"tagIds": ["664abc000000000000000010", "664abc000000000000000011"],
"rules": [
{
"targetUrl": "https://example.com/ua-mobile",
"isDefault": false,
"country": ["UA"],
"device": ["mobile"],
"os": ["iOS", "Android"],
"timeStart": "08:00",
"timeEnd": "22:00",
"daysOfWeek": [1, 2, 3, 4, 5]
},
{
"targetUrl": "https://example.com/de",
"isDefault": false,
"country": ["DE", "AT", "CH"],
"device": ["desktop"],
"browser": ["Chrome", "Firefox"]
},
{
"targetUrl": "https://example.com",
"isDefault": true
}
]
}'
Respuesta 200 OK
{
"message": "Link \"Summer campaign\" successfully created.",
"id": "664abc123def456789000001",
"slug": "summer-2025",
"fullLink": "https://go.mycompany.com/summer-2025"
}
Respuestas de error
| Estado | Cuerpo | Causa |
|---|---|---|
400 | {"error": "Name is required."} | Falta el campo name |
400 | {"error": "rules must be a non-empty array."} | rules falta o está vacío |
400 | {"error": "Domain is not available for this workspace."} | El domain indicado no es un dominio verificado de este espacio de trabajo |
403 | {"licenseLimitReached": true, ...} | Se alcanzó la cuota del plan de enlaces o reglas |
409 | {"error": "This slug is already taken."} | El slug indicado ya está en uso en este dominio |
Actualizar un enlace
PUT /link/update Solo se cambian los campos que indiques; el resto permanece igual.
Petición
PUT https://api.revolink.link/apiv1/link/update
Content-Type: application/json
X-Api-Key: rvlnk_your_api_key_here
Campos del cuerpo
| Campo | Tipo | Obligatorio | Descripción |
|---|---|---|---|
workspaceId | string | ✅ | ObjectId del espacio de trabajo |
linkId | string | ✅ | ObjectId del enlace que se va a actualizar |
name | string | — | Nuevo nombre visible |
description | string | — | Nueva descripción |
rules | Rule[] | — | Sustituye todas las reglas de enrutamiento |
active | boolean | — | Activa o desactiva el enlace |
clicksLimit | number | — | Nuevo límite de clics. Pasa null para quitar el límite |
expirationDate | string | — | Nueva fecha y hora de caducidad. Pasa null para quitar la caducidad |
tagIds | string[] | — | Sustituye la lista de etiquetas |
Ejemplo mínimo (desactivar un enlace)
curl -X PUT https://api.revolink.link/apiv1/link/update \
-H "Content-Type: application/json" \
-H "X-Api-Key: rvlnk_your_api_key_here" \
-d '{
"workspaceId": "664abc000000000000000001",
"linkId": "664abc123def456789000001",
"active": false
}'
Ejemplo completo (actualizar todos los campos)
curl -X PUT https://api.revolink.link/apiv1/link/update \
-H "Content-Type: application/json" \
-H "X-Api-Key: rvlnk_your_api_key_here" \
-d '{
"workspaceId": "664abc000000000000000001",
"linkId": "664abc123def456789000001",
"name": "Summer campaign (updated)",
"description": "Updated description",
"active": true,
"clicksLimit": 50000,
"expirationDate": "2025-12-31T23:59:59Z",
"tagIds": ["664abc000000000000000012"],
"rules": [
{
"targetUrl": "https://example.com/ua-mobile-v2",
"isDefault": false,
"country": ["UA", "PL"],
"device": ["mobile"]
},
{
"targetUrl": "https://example.com/v2",
"isDefault": true
}
]
}'
Ejemplo para quitar límites
curl -X PUT https://api.revolink.link/apiv1/link/update \
-H "Content-Type: application/json" \
-H "X-Api-Key: rvlnk_your_api_key_here" \
-d '{
"workspaceId": "664abc000000000000000001",
"linkId": "664abc123def456789000001",
"clicksLimit": null,
"expirationDate": null
}'
Respuesta 200 OK
{
"message": "Link updated.",
"id": "664abc123def456789000001"
}
Respuestas de error
| Estado | Cuerpo | Causa |
|---|---|---|
400 | {"error": "Invalid linkId format."} | linkId no es un ObjectId válido |
403 | {"error": "You do not have permission to edit this link."} | El enlace pertenece a otro espacio de trabajo |
403 | {"licenseLimitReached": true, ...} | Se alcanzó el límite de reglas del plan actual |
404 | {"error": "Link not found."} | No existe ningún enlace con este ID |
Eliminar un enlace
DELETE /link/delete
Petición
DELETE https://api.revolink.link/apiv1/link/delete
Content-Type: application/json
X-Api-Key: rvlnk_your_api_key_here
Campos del cuerpo
| Campo | Tipo | Obligatorio | Descripción |
|---|---|---|---|
workspaceId | string | ✅ | ObjectId del espacio de trabajo |
linkId | string | ✅ | ObjectId del enlace que se va a eliminar |
Ejemplo
curl -X DELETE https://api.revolink.link/apiv1/link/delete \
-H "Content-Type: application/json" \
-H "X-Api-Key: rvlnk_your_api_key_here" \
-d '{
"workspaceId": "664abc000000000000000001",
"linkId": "664abc123def456789000001"
}'
Respuesta 200 OK
{
"message": "Link deleted."
}
Respuestas de error
| Estado | Cuerpo | Causa |
|---|---|---|
400 | {"error": "Invalid linkId format."} | linkId no es un ObjectId válido |
403 | {"error": "You do not have permission to delete this link."} | El enlace pertenece a otro espacio de trabajo |
404 | {"error": "Link not found."} | No existe ningún enlace con este ID |
Crear enlaces de forma masiva
POST /links/bulk-create Hasta 100 enlaces por llamada. Cada enlace se procesa de forma independiente: si uno falla, los demás continúan.
Petición
POST https://api.revolink.link/apiv1/links/bulk-create
Content-Type: application/json
X-Api-Key: rvlnk_your_api_key_here
Campos del cuerpo
| Campo | Tipo | Obligatorio | Descripción |
|---|---|---|---|
workspaceId | string | ✅ | ObjectId del espacio de trabajo |
links | LinkInput[] | ✅ | Array de objetos de enlace. Máximo 100 elementos |
Cada elemento de links acepta los mismos campos que /link/create, salvo workspaceId (se indica una sola vez en el nivel superior).
Ejemplo
curl -X POST https://api.revolink.link/apiv1/links/bulk-create \
-H "Content-Type: application/json" \
-H "X-Api-Key: rvlnk_your_api_key_here" \
-d '{
"workspaceId": "664abc000000000000000001",
"links": [
{
"name": "Campaign — Ukraine mobile",
"slug": "ua-mob",
"description": "UA mobile audience",
"active": true,
"clicksLimit": 5000,
"expirationDate": "2025-12-31T23:59:59Z",
"tagIds": ["664abc000000000000000010"],
"rules": [
{
"targetUrl": "https://example.com/ua",
"isDefault": false,
"country": ["UA"],
"device": ["mobile"]
},
{
"targetUrl": "https://example.com",
"isDefault": true
}
]
},
{
"name": "Campaign — Germany",
"rules": [
{
"targetUrl": "https://example.com/de",
"isDefault": false,
"country": ["DE", "AT", "CH"]
},
{
"targetUrl": "https://example.com",
"isDefault": true
}
]
},
{
"name": "Simple redirect",
"rules": [
{
"targetUrl": "https://example.com/simple",
"isDefault": true
}
]
}
]
}'
Respuesta 200 OK
La respuesta siempre devuelve 200, aunque algunos elementos hayan fallado. Consulta el array failed para ver los errores de cada elemento.
{
"message": "Bulk create complete: 3 created, 0 failed.",
"created": [
{
"id": "664abc123def456789000001",
"slug": "ua-mob",
"fullLink": "https://rvlnk.link/ua-mob",
"name": "Campaign — Ukraine mobile"
},
{
"id": "664abc123def456789000002",
"slug": "xk7r2p",
"fullLink": "https://rvlnk.link/xk7r2p",
"name": "Campaign — Germany"
},
{
"id": "664abc123def456789000003",
"slug": "m9qw1z",
"fullLink": "https://rvlnk.link/m9qw1z",
"name": "Simple redirect"
}
],
"failed": []
}
Ejemplo de fallo parcial:
{
"message": "Bulk create complete: 2 created, 1 failed.",
"created": [
{
"id": "664abc123def456789000001",
"slug": "ua-mob",
"fullLink": "https://rvlnk.link/ua-mob",
"name": "Campaign — Ukraine mobile"
}
],
"failed": [
{
"input": {
"description": "Missing name and rules"
},
"error": "Each link must have name and rules."
}
]
}
Respuestas de error
| Estado | Cuerpo | Causa |
|---|---|---|
400 | {"error": "links must be a non-empty array."} | links falta o está vacío |
400 | {"error": "Maximum 100 links per request."} | Se enviaron más de 100 elementos |
403 | {"licenseLimitReached": true, ...} | Se superaría la cuota del plan |
Analítica de un enlace
GET /links/{id}/analytics
Devuelve estadísticas de clics de un solo enlace. Disponible para todos los miembros del espacio de trabajo.
Petición
GET https://api.revolink.link/apiv1/links/{id}/analytics?workspaceId=...&from=...&to=...
X-Api-Key: rvlnk_your_api_key_here
Parámetros de consulta
| Parámetro | Tipo | Obligatorio | Descripción |
|---|---|---|---|
workspaceId | string | ✅ | ObjectId del espacio de trabajo |
from | string | — | Fecha de inicio en formato YYYY-MM-DD. Por defecto, desde el principio de los tiempos |
to | string | — | Fecha de fin en formato YYYY-MM-DD. Por defecto, hoy |
Ejemplo
curl "https://api.revolink.link/apiv1/links/664abc123def456789000001/analytics?workspaceId=664abc000000000000000001&from=2025-01-01&to=2025-04-30" \
-H "X-Api-Key: rvlnk_your_api_key_here"
Respuesta 200 OK
{
"totals": {
"total": 1540,
"periodTotal": 320,
"unique": 210
},
"dailyTraffic": {
"2025-04-28": 45,
"2025-04-29": 61,
"2025-04-30": 38
},
"countries": {
"UA": { "title": "Ukraine", "value": 180, "flag": "UA" },
"DE": { "title": "Germany", "value": 54, "flag": "DE" }
},
"cities": {
"Kyiv": { "title": "Kyiv", "value": 92, "flag": "UA" }
},
"devices": {
"mobile": { "title": "Mobile", "value": 210 },
"desktop": { "title": "Desktop", "value": 110 }
},
"browsers": {
"Chrome": { "title": "Chrome", "value": 198 }
},
"os": {
"Android": { "title": "Android", "value": 140 }
},
"referrers": {
"instagram.com": { "title": "instagram.com", "value": 95 },
"Direct": { "title": "Direct", "value": 225 }
},
"rulesStats": {
"rule-id-1": {
"name": "Ukraine mobile",
"targetUrl": "https://example.com/ua",
"clicks": 140,
"uniqueClicks": 95,
"referrers": {
"Direct": { "title": "Direct", "value": 80 }
}
}
},
"abVariantsStats": {
"1714000000000": {
"name": "Variant A",
"targetUrl": "https://example.com/a",
"clicks": 185,
"uniqueClicks": 122,
"referrers": {}
}
}
}
Descripción de los campos:
| Campo | Descripción |
|---|---|
totals.total | Clics totales de este enlace de todos los tiempos |
totals.periodTotal | Clics dentro del rango de fechas solicitado |
totals.unique | Visitantes únicos dentro del rango de fechas (por IP + user agent) |
dailyTraffic | Clics por día dentro del rango de fechas. Todos los días del rango están presentes, incluso si el valor es 0 |
countries / cities / devices / browsers / os | Desglose por dimensión. Cada clave corresponde a { title, value, flag? } |
referrers | Fuentes de tráfico. "Direct" significa que no hay cabecera de referente |
rulesStats | Desglose por regla. Cada clave es el ID de la regla. Contiene name, targetUrl, clicks, uniqueClicks y referrers |
abVariantsStats | Desglose por variante A/B. Cada clave es el ID de la variante. Contiene name, targetUrl, clicks, uniqueClicks y referrers. Objeto vacío si la prueba A/B no está activada |
Respuestas de error
| Estado | Cuerpo | Causa |
|---|---|---|
400 | {"error": "Invalid link id."} | id no es un ObjectId válido |
404 | {"error": "Link not found in this workspace."} | El enlace no existe o pertenece a otro espacio de trabajo |
Analítica de todos los enlaces
GET /links/analytics
Devuelve estadísticas de clics agregadas de todos los enlaces del espacio de trabajo. Disponible solo para el propietario y los gestores del espacio de trabajo.
Petición
GET https://api.revolink.link/apiv1/links/analytics?workspaceId=...&from=...&to=...
X-Api-Key: rvlnk_your_api_key_here
Parámetros de consulta
| Parámetro | Tipo | Obligatorio | Descripción |
|---|---|---|---|
workspaceId | string | ✅ | ObjectId del espacio de trabajo |
from | string | — | Fecha de inicio en formato YYYY-MM-DD. Por defecto, desde el principio de los tiempos |
to | string | — | Fecha de fin en formato YYYY-MM-DD. Por defecto, hoy |
Ejemplo
curl "https://api.revolink.link/apiv1/links/analytics?workspaceId=664abc000000000000000001&from=2025-04-01&to=2025-04-30" \
-H "X-Api-Key: rvlnk_your_api_key_here"
Respuesta 200 OK
{
"totals": {
"total": 8420,
"periodTotal": 1750,
"unique": 1120
},
"dailyTraffic": {
"2025-04-01": 52,
"2025-04-02": 78
},
"links": {
"664abc123def456789000001": { "title": "Summer campaign", "value": 920 },
"664abc123def456789000002": { "title": "Product launch", "value": 830 }
},
"countries": {
"UA": { "title": "Ukraine", "value": 640, "flag": "UA" }
},
"cities": {
"Kyiv": { "title": "Kyiv", "value": 310, "flag": "UA" }
},
"devices": {
"mobile": { "title": "Mobile", "value": 980 },
"desktop": { "title": "Desktop", "value": 770 }
},
"browsers": {
"Chrome": { "title": "Chrome", "value": 1050 }
},
"os": {
"Android": { "title": "Android", "value": 620 },
"iOS": { "title": "iOS", "value": 360 }
}
}
Descripción de los campos:
| Campo | Descripción |
|---|---|
totals.total | Clics totales de todos los enlaces del espacio de trabajo dentro del rango de fechas |
totals.periodTotal | Igual que total: clics filtrados por el rango de fechas solicitado |
totals.unique | Visitantes únicos en el rango de fechas |
links | Desglose por enlace. Cada clave es el ObjectId del enlace. El valor contiene title (nombre del enlace) y value (número de clics) |
dailyTraffic | Clics por día de todos los enlaces. Todos los días del rango están presentes |
countries / cities / devices / browsers / os | Desglose agregado de todos los enlaces. Cada clave corresponde a { title, value, flag? } |
Respuestas de error
| Estado | Cuerpo | Causa |
|---|---|---|
403 | {"error": "Only workspace owner or manager can access all links analytics."} | El usuario autenticado es un miembro normal, no propietario ni gestor |
INFO
Los cuerpos de las respuestas y los mensajes de error de la API están siempre en inglés, tal como los devuelve el servidor. La traducción solo afecta a las descripciones.