Resolva colisões de slug com um sufixo numérico
O resolvedor de colisões compara o slug exato que você deseja com os slugs já ocupados.
Executar grátis
Quando o valor está disponível, ele o devolve sem alterações. Quando já está em uso, verifica alternativas numéricas como -2, -3 e as seguintes até encontrar a primeira livre. É um componente pequeno e determinístico para sistemas de publicação, importações, geradores de documentação e qualquer fluxo que precise atribuir uma rota de URL exclusiva sem substituir conteúdo existente por engano.
Preserve o slug desejado sempre que possível
Um bom resolvedor de colisões deve alterar uma URL somente quando for necessário. Envie o valor proposto em desired_slug e informe todos os valores ocupados em used_slugs. As comparações são exatas e diferenciam maiúsculas de minúsculas. Se a proposta não aparecer no conjunto ocupado, o resultado conterá o slug original e indicará que não houve colisão. A ferramenta não converte letras, não remove espaços nas extremidades, não translitera nem troca pontuação, pois essas transformações pertencem à etapa anterior de criação do slug. Separar as responsabilidades evita mudanças inesperadas de URL e torna a saída reproduzível em builds, migrações e testes. Um slug desejado vazio é rejeitado, em vez de virar um sufixo arbitrário, porque isso esconderia um título ausente ou um mapeamento anterior com defeito. Valores duplicados na lista não mudam a resposta; a consulta os consolida naturalmente, então você não precisa limpar a lista para obter um resultado estável.
Escolha o primeiro sufixo numérico disponível
Quando o slug exato está ocupado, a seleção começa em 2, seguindo a convenção comum em que a rota sem sufixo representa o primeiro item e o item seguinte recebe -2. Depois, os candidatos são verificados em ordem crescente: desejado-2, desejado-3, desejado-4 e assim por diante. O processo para no primeiro candidato ausente do conjunto informado. Dessa forma, as lacunas são reutilizadas de maneira previsível. Por exemplo, se report, report-2 e report-4 estiverem ocupados, o retorno será report-3. A comparação considera strings completas; portanto, annual-report e report-old não criam colisão. Uma terminação numérica já existente é tratada como parte literal do valor, sem interpretação ou reescrita: se release-2 for solicitado e estiver ocupado, o primeiro candidato será release-2-2. Esse comportamento evita suposições sobre a intenção e garante que entradas idênticas sempre produzam a mesma saída, sem depender de banco de dados, relógio, aleatoriedade, localidade ou ordem de execução.
Use o resultado com segurança na publicação
Esta capacidade é útil quando sua aplicação já sabe quais slugs estão reservados. Reúna esses valores, envie-os com o slug desejado e use o retorno no novo registro. A resposta também informa se houve colisão e, quando há sufixo, qual número foi selecionado. Esses dados podem alimentar logs, prévias ou mensagens que expliquem por que a URL ficou diferente da proposta inicial. A operação não reserva o valor retornado; sistemas com gravações simultâneas ainda devem impor uma restrição exclusiva e tentar novamente com a lista atualizada caso outro processo ocupe o mesmo slug. Em importações em lote, acrescente cada atribuição bem-sucedida ao conjunto local antes de resolver a próxima linha. Como a comparação é exata, aplique antes e de modo consistente sua política de URL: use um gerador de slugs se precisar normalizar caixa, Unicode, espaços ou pontuação. Cada solicitação de API custa US$ 0,002, e a mesma lógica determinística pode ser executada no navegador para verificações interativas.
Casos de uso
Publique uma página sem substituir outra
Mantenha a rota preferida do editor quando estiver livre ou atribua a primeira alternativa numerada disponível quando já estiver ocupada.
Importe registros com URLs exclusivas e estáveis
Resolva cada slug preparado diante das rotas existentes e recém-atribuídas para dar sufixos determinísticos a títulos repetidos.
Gere rotas de documentação
Impeça que títulos ou páginas geradas duplicadas reivindiquem a mesma rota, mantendo caminhos legíveis e previsíveis.
Perguntas frequentes
O que acontece quando o slug desejado está livre?
Ele é devolvido sem alterações, e collision é false.
Qual sufixo é testado primeiro?
O resolvedor começa com -2 e depois verifica -3, -4 e valores maiores até encontrar o primeiro livre.
A ferramenta transforma texto em slug de URL?
Não. Ela compara e estende o valor exato recebido. Use antes um gerador se precisar normalizar caixa, espaços, pontuação ou Unicode.
As comparações diferenciam maiúsculas?
Sim. Product e Product são idênticos, enquanto Product e product são tratados como strings diferentes.
A capacidade reserva o slug retornado?
Não. Ela calcula um candidato com base na lista recebida. Seu armazenamento deve impor exclusividade ao gravar o registro.
Quanto custa uma solicitação de API?
Cada solicitação custa US$ 0,002.
Para desenvolvedores — acesso via API
Tudo nesta página está disponível via API. Esta seção é para equipes que querem integrar a ferramenta aos próprios sistemas; quem não precisa disso pode simplesmente usar a ferramenta acima.
Endpoint
Autenticação por token Bearer. Um único POST coloca a tarefa na fila; o resultado chega por webhook ou link assinado.
Chame do seu código
curl -X POST https://api.kit.forhosting.com/dev/slug-collision-resolve \
-H "Authorization: Bearer $KIT_KEY" \
-H "Content-Type: application/json" \
-d '{"desired_slug":"product-guide","used_slugs":["product-guide","product-guide-2"]}'const res = await fetch("https://api.kit.forhosting.com/dev/slug-collision-resolve", {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.KIT_KEY}`,
"Content-Type": "application/json"
},
body: JSON.stringify({
"desired_slug": "product-guide",
"used_slugs": [
"product-guide",
"product-guide-2"
]
})
});
const { task_id } = await res.json();import os, requests
res = requests.post(
"https://api.kit.forhosting.com/dev/slug-collision-resolve",
headers={"Authorization": f"Bearer {os.environ['KIT_KEY']}"},
json={
"desired_slug": "product-guide",
"used_slugs": [
"product-guide",
"product-guide-2"
]
},
)
task_id = res.json()["task_id"]<?php
$res = file_get_contents("https://api.kit.forhosting.com/dev/slug-collision-resolve", false, stream_context_create([
"http" => [
"method" => "POST",
"header" => "Authorization: Bearer " . getenv("KIT_KEY") . "\r\nContent-Type: application/json",
"content" => '{"desired_slug":"product-guide","used_slugs":["product-guide","product-guide-2"]}',
],
]));
$task = json_decode($res, true);body := bytes.NewBufferString(`{"desired_slug":"product-guide","used_slugs":["product-guide","product-guide-2"]}`)
req, _ := http.NewRequest("POST", "https://api.kit.forhosting.com/dev/slug-collision-resolve", body)
req.Header.Set("Authorization", "Bearer "+os.Getenv("KIT_KEY"))
req.Header.Set("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)Exemplo de requisição
{
"desired_slug": "product-guide",
"used_slugs": [
"product-guide",
"product-guide-2"
]
}Exemplo de resposta
{
"task_id": "tsk_a1b2c3d4e5f6a1b2c3d4e5f6",
"type": "dev.slug_collision_resolve",
"status": "queued",
"_links": {
"result": "/tasks/tsk_…/result"
}
}A API é assíncrona: cada chamada devolve um task_id na hora. Se preferir polling, consulte o status a até 1 requisição por segundo.
Preço
Preço publicado, sem tokens nem créditos escondidos. Tarefa que falha não é cobrada.
Limites
max_used_slugs | 10000 |
max_slug_chars | 10000 |
Erros
| HTTP | Código | O que significa |
|---|---|---|
401 | unauthorized | Token ausente ou inválido. Confira o header Authorization. |
402 | insufficient_balance | Saldo insuficiente para esta tarefa. Faça uma recarga e tente de novo. |
404 | unknown_type | Esse tipo de tarefa não existe. Confira o campo type no catálogo. |
429 | rate_limited | Muitas requisições em pouco tempo. Espere um instante e tente de novo. |