Links (API v1, removida)
Estes endpoints não funcionam mais
Os seis endpoints da API v1 abaixo foram substituídos pela API v2 e agora respondem 410 Gone com a substituição na resposta. Passe para a API v2. As seções a seguir descrevem o formato antigo e são mantidas apenas para ajudar na migração.
Para onde cada endpoint foi movido
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 |
O que muda para você: a chave vai em Authorization: Bearer <key> (ou X-Api-Key), o espaço de trabalho vai no cabeçalho X-Workspace-Id e não mais no corpo nem na query string, um link é identificado pelo id na URL e as respostas vêm envolvidas em { "data": … }. Veja a autenticação da API v2 e Erros.
Endpoints antigos (referência para migração)
| Método | Caminho | Descrição |
|---|---|---|
POST | /link/create | Criar um link |
PUT | /link/update | Atualizar um link |
DELETE | /link/delete | Excluir um link |
POST | /links/bulk-create | Criar links em massa |
GET | /links/{id}/analytics | Análises de um link |
GET | /links/analytics | Análises de todos os links |
Objeto de regra
As regras definem para onde um link redireciona. Todo link deve ter pelo menos uma regra com isDefault: true: é o destino de reserva quando as condições de nenhuma outra regra são atendidas.
As regras não padrão são avaliadas em ordem. Vence a primeira regra cujas condições são todas atendidas. Se nenhuma regra corresponder, a regra padrão é usada.
Os IDs das regras são gerados automaticamente pelo servidor: não inclua id na sua requisição.
Restrições:
- Exatamente uma regra por link deve ter
isDefault: true - A regra padrão é uma reserva pura: não pode ter nenhuma condição (
country,city,device,os,browser,timeStart,timeEnd,daysOfWeek). As condições só são permitidas em regras não padrão timeStartetimeEnddevem ser informados juntos ou omitidos juntos
| Campo | Tipo | Obrigatório | Descrição |
|---|---|---|---|
targetUrl | string | ✅ | URL de destino. Qualquer URL válida, inclusive deep links (por ex. youtube://, myapp://) |
isDefault | boolean | ✅ | Exatamente uma regra por link deve ter true |
country | string[] | — | Códigos de país ISO 3166-1 alpha-2 (por ex. ["UA", "PL"]). Só correspondem visitantes desses países |
city | string[] | — | Nomes de cidade (por ex. ["Kyiv", "Warsaw"]). Exige que country seja informado: não é possível usar cidade sem país |
device | string[] | — | Tipos de dispositivo. Valores aceitos: "desktop", "mobile", "tablet", "console", "smarttv", "wearable", "embedded" |
os | string[] | — | Sistemas operacionais. Valores aceitos: "Windows", "macOS", "Linux", "iOS", "Android" |
browser | string[] | — | Navegadores. Valores aceitos: "Chrome", "Firefox", "Safari", "Edge", "Opera", "Brave" |
timeStart | string | — | Início da janela de horário ativa no formato "HH:MM" (por ex. "09:00") |
timeEnd | string | — | Fim da janela de horário ativa no formato "HH:MM" (por ex. "18:00") |
daysOfWeek | number[] | — | Dias em que a regra está ativa. 0 = domingo … 6 = sábado (por ex. [1,2,3,4,5] para dias úteis) |
Exemplo completo de regra (todos os campos de condição opcionais):
{
"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 teste A/B
O teste A/B divide o tráfego aleatoriamente entre várias URLs de destino de acordo com os pesos. Quando abTest.enabled é true, as regras de roteamento são ignoradas: cada visitante é enviado a uma das variantes.
| Campo | Tipo | Obrigatório | Descrição |
|---|---|---|---|
enabled | boolean | ✅ | Defina true para ativar o teste A/B |
variants | Variant[] | ✅ | Lista de variantes. Mínimo de 2 quando ativado |
Campos da variante:
| Campo | Tipo | Obrigatório | Descrição |
|---|---|---|---|
id | string | ✅ | Identificador único da variante. Use qualquer string estável (por ex. um carimbo de data/hora): o servidor a armazena como está para o rastreamento |
name | string | ✅ | Nome de exibição (por ex. "Variant A") |
url | string | ✅ | URL de destino desta variante |
weight | number | ✅ | Parte do tráfego. Os pesos de todas as variantes devem somar exatamente 100 |
Exemplo:
{
"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 desativar o teste A/B ao atualizar um link:
{
"abTest": { "enabled": false, "variants": [] }
}
Objeto de configurações do QR
Controla a aparência visual do QR code gerado para um link.
| Campo | Tipo | Descrição |
|---|---|---|
color | string | Cor de primeiro plano em formato hex. Padrão: "#000000" |
bgColor | string | Cor de fundo em formato hex. Padrão: "#ffffff" |
useLogo | boolean | Se um logotipo deve ser inserido no centro do QR code. Padrão: false |
logo | string | Imagem do logotipo como data URL (por ex. "data:image/png;base64,...") ou URL. Obrigatório quando useLogo é true |
Exemplo:
{
"qrSettings": {
"color": "#1a1a2e",
"bgColor": "#ffffff",
"useLogo": true,
"logo": "https://example.com/logo.png"
}
}
Criar um link
POST /link/create
Requisição
POST https://api.revolink.link/apiv1/link/create
Content-Type: application/json
X-Api-Key: rvlnk_your_api_key_here
Campos do corpo
| Campo | Tipo | Obrigatório | Descrição |
|---|---|---|---|
workspaceId | string | ✅ | ObjectId do espaço de trabalho |
name | string | ✅ | Nome de exibição do link |
rules | Rule[] | ✅ | Regras de roteamento. É necessária pelo menos uma regra com isDefault: true |
description | string | — | Descrição interna (não exibida aos visitantes). Máx. 1000 caracteres |
slug | string | — | Slug de URL personalizado. Gerado automaticamente se omitido. Apenas letras minúsculas, números e hifens. Máx. 100 caracteres |
domain | string | — | Hostname do domínio personalizado (por ex. "go.mycompany.com"). Deve ser um domínio verificado no espaço de trabalho. Padrão: rvlnk.link |
active | boolean | — | Padrão: true |
clicksLimit | number | — | Inteiro positivo. Sem limite se omitido |
expirationDate | string | — | Data e hora ISO 8601. Deve ser futura |
tagIds | string[] | — | Array de ObjectIds de tags |
abTest | object | — | Configuração do teste A/B. Veja Objeto de teste A/B |
qrSettings | object | — | Aparência do QR code. Veja Objeto de configurações do QR |
Exemplo 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
}
]
}'
Exemplo completo (todos os 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
}
]
}'
Resposta 200 OK
{
"message": "Link \"Summer campaign\" successfully created.",
"id": "664abc123def456789000001",
"slug": "summer-2025",
"fullLink": "https://go.mycompany.com/summer-2025"
}
Respostas de erro
| Status | Corpo | Causa |
|---|---|---|
400 | {"error": "Name is required."} | O campo name está ausente |
400 | {"error": "rules must be a non-empty array."} | rules está ausente ou vazio |
400 | {"error": "Domain is not available for this workspace."} | O domain informado não é um domínio verificado deste espaço de trabalho |
403 | {"licenseLimitReached": true, ...} | A cota do plano de links ou regras foi atingida |
409 | {"error": "This slug is already taken."} | O slug informado já está em uso neste domínio |
Atualizar um link
PUT /link/update Só os campos que você informar são alterados; os demais permanecem como estão.
Requisição
PUT https://api.revolink.link/apiv1/link/update
Content-Type: application/json
X-Api-Key: rvlnk_your_api_key_here
Campos do corpo
| Campo | Tipo | Obrigatório | Descrição |
|---|---|---|---|
workspaceId | string | ✅ | ObjectId do espaço de trabalho |
linkId | string | ✅ | ObjectId do link a atualizar |
name | string | — | Novo nome de exibição |
description | string | — | Nova descrição |
rules | Rule[] | — | Substitui todas as regras de roteamento |
active | boolean | — | Ativa ou desativa o link |
clicksLimit | number | — | Novo limite de cliques. Envie null para remover o limite |
expirationDate | string | — | Nova data e hora de expiração. Envie null para remover a expiração |
tagIds | string[] | — | Substitui a lista de tags |
Exemplo mínimo (desativar um link)
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
}'
Exemplo completo (atualizar todos os 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
}
]
}'
Exemplo para remover limites
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
}'
Resposta 200 OK
{
"message": "Link updated.",
"id": "664abc123def456789000001"
}
Respostas de erro
| Status | Corpo | Causa |
|---|---|---|
400 | {"error": "Invalid linkId format."} | linkId não é um ObjectId válido |
403 | {"error": "You do not have permission to edit this link."} | O link pertence a outro espaço de trabalho |
403 | {"licenseLimitReached": true, ...} | O limite de regras do plano atual foi atingido |
404 | {"error": "Link not found."} | Não existe link com este ID |
Excluir um link
DELETE /link/delete
Requisição
DELETE https://api.revolink.link/apiv1/link/delete
Content-Type: application/json
X-Api-Key: rvlnk_your_api_key_here
Campos do corpo
| Campo | Tipo | Obrigatório | Descrição |
|---|---|---|---|
workspaceId | string | ✅ | ObjectId do espaço de trabalho |
linkId | string | ✅ | ObjectId do link a excluir |
Exemplo
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"
}'
Resposta 200 OK
{
"message": "Link deleted."
}
Respostas de erro
| Status | Corpo | Causa |
|---|---|---|
400 | {"error": "Invalid linkId format."} | linkId não é um ObjectId válido |
403 | {"error": "You do not have permission to delete this link."} | O link pertence a outro espaço de trabalho |
404 | {"error": "Link not found."} | Não existe link com este ID |
Criar links em massa
POST /links/bulk-create Até 100 links por chamada. Cada link é processado de forma independente: se um falhar, os demais continuam.
Requisição
POST https://api.revolink.link/apiv1/links/bulk-create
Content-Type: application/json
X-Api-Key: rvlnk_your_api_key_here
Campos do corpo
| Campo | Tipo | Obrigatório | Descrição |
|---|---|---|---|
workspaceId | string | ✅ | ObjectId do espaço de trabalho |
links | LinkInput[] | ✅ | Array de objetos de link. Máximo de 100 itens |
Cada item de links aceita os mesmos campos de /link/create, exceto workspaceId (informado uma vez no nível superior).
Exemplo
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
}
]
}
]
}'
Resposta 200 OK
A resposta sempre retorna 200, mesmo que alguns itens tenham falhado. Confira o array failed para ver os erros de cada item.
{
"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": []
}
Exemplo de falha 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."
}
]
}
Respostas de erro
| Status | Corpo | Causa |
|---|---|---|
400 | {"error": "links must be a non-empty array."} | links está ausente ou vazio |
400 | {"error": "Maximum 100 links per request."} | Foram enviados mais de 100 itens |
403 | {"licenseLimitReached": true, ...} | A cota do plano seria excedida |
Análises de um link
GET /links/{id}/analytics
Retorna estatísticas de cliques de um único link. Disponível para todos os membros do espaço de trabalho.
Requisição
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 | Obrigatório | Descrição |
|---|---|---|---|
workspaceId | string | ✅ | ObjectId do espaço de trabalho |
from | string | — | Data inicial no formato YYYY-MM-DD. Padrão: o início dos tempos |
to | string | — | Data final no formato YYYY-MM-DD. Padrão: hoje |
Exemplo
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"
Resposta 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": {}
}
}
}
Descrição dos campos:
| Campo | Descrição |
|---|---|
totals.total | Total de cliques deste link em todo o período |
totals.periodTotal | Cliques dentro do intervalo de datas solicitado |
totals.unique | Visitantes únicos dentro do intervalo de datas (por IP + user agent) |
dailyTraffic | Cliques por dia dentro do intervalo de datas. Todos os dias do intervalo estão presentes, mesmo que o valor seja 0 |
countries / cities / devices / browsers / os | Detalhamento por dimensão. Cada chave corresponde a { title, value, flag? } |
referrers | Origens de tráfego. "Direct" significa que não há cabeçalho de referenciador |
rulesStats | Detalhamento por regra. Cada chave é o ID da regra. Contém name, targetUrl, clicks, uniqueClicks e referrers |
abVariantsStats | Detalhamento por variante A/B. Cada chave é o ID da variante. Contém name, targetUrl, clicks, uniqueClicks e referrers. Objeto vazio se o teste A/B não estiver ativado |
Respostas de erro
| Status | Corpo | Causa |
|---|---|---|
400 | {"error": "Invalid link id."} | id não é um ObjectId válido |
404 | {"error": "Link not found in this workspace."} | O link não existe ou pertence a outro espaço de trabalho |
Análises de todos os links
GET /links/analytics
Retorna estatísticas de cliques agregadas de todos os links do espaço de trabalho. Disponível somente para o proprietário e os gerentes do espaço de trabalho.
Requisição
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 | Obrigatório | Descrição |
|---|---|---|---|
workspaceId | string | ✅ | ObjectId do espaço de trabalho |
from | string | — | Data inicial no formato YYYY-MM-DD. Padrão: o início dos tempos |
to | string | — | Data final no formato YYYY-MM-DD. Padrão: hoje |
Exemplo
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"
Resposta 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 }
}
}
Descrição dos campos:
| Campo | Descrição |
|---|---|
totals.total | Total de cliques de todos os links do espaço de trabalho dentro do intervalo de datas |
totals.periodTotal | Igual a total: cliques filtrados pelo intervalo de datas solicitado |
totals.unique | Visitantes únicos no intervalo de datas |
links | Detalhamento por link. Cada chave é o ObjectId do link. O valor contém title (nome do link) e value (número de cliques) |
dailyTraffic | Cliques por dia de todos os links. Todos os dias do intervalo estão presentes |
countries / cities / devices / browsers / os | Detalhamento agregado de todos os links. Cada chave corresponde a { title, value, flag? } |
Respostas de erro
| Status | Corpo | Causa |
|---|---|---|
403 | {"error": "Only workspace owner or manager can access all links analytics."} | O usuário autenticado é um membro comum, não proprietário nem gerente |
INFO
Os corpos das respostas e as mensagens de erro da API estão sempre em inglês, como o servidor os devolve. A tradução afeta apenas as descrições.