API do time Encurtee
Integração por chave de API (Team API v1) e REST com sessão para a app (/api/v1/teams). Tudo no mesmo domínio (Nitro /api).
curl -s -H "Authorization: Bearer YOUR_API_KEY" "https://encurtee.me/api/v1/teams/TEAM_ID/ping"Visão geral
Existem duas famílias de endpoints: (1) Team API v1, para automação com chave de API e plano que inclua API; (2) rotas /api/v1/teams com sessão Supabase (cookies), usadas pelo painel após login.
Em ambas, o segmento :id do time pode ser o UUID interno ou o public_id numérico (5-12 dígitos), exceto nas rotas em que o usuário só interage com os próprios dados (ex.: listagem de times).
Mensagens de erro e sucesso seguem o cookie i18n_redirected (pt ou en), quando o servidor as traduz.
Dois tipos de integração
Prefixo /api/v1/teams/:id. Autenticação com Authorization: Bearer ou cabeçalhos X-Team-Api-Key / X-Encurtee-Team-Key. Hoje: GET ping e POST links (corpo mínimo: url e title opcional).
Prefixo /api/v1/teams (e /api/v1/teams/:id/…). Requer usuário autenticado (mesma sessão do navegador: cookies). Permissões por função no time (owner, admin, etc.).
Parâmetro :id
Onde aparece :id nas rotas do time, aceita UUID ou public_id numérico resolvido no banco de dados.
Autenticação - Team API v1
Aplica-se aos endpoints sob /api/v1/teams/:id/ (recomendado).
Cabeçalho Authorization (recomendado)
Authorization: Bearer YOUR_FULL_API_KEYCabeçalhos alternativos
X-Team-Api-Key ou X-Encurtee-Team-Key com o valor da chave.
Comportamento com Authorization
Se Authorization estiver presente, só conta Bearer com token não vazio (sem fallback para X-*).
Modelo da chave de API do time
Hoje existe uma única chave ativa por time (salva como hash no banco de dados). Regenerar ou revogar substitui ou remove essa chave - útil para rotação e emergências.
Quem gere a chave: membros com permissão edit_team (normalmente dono ou admin). A chave permite automatizar pedidos sem cookie de sessão; trate-a como segredo (não commite em repositórios públicos).
Team API v1 - ping e links
Expandir para parâmetros, query e exemplos
GET/api/v1/teams/:id/pingConfirma a chave para o time. Consome tokens de utilização da API do time.
Resposta de sucesso
JSON com success: true e message traduzida.
{
"success": true,
"message": "Chave de API do time válida"
}POST/api/v1/teams/:id/linksCria link no time (owner como criador). Validação de URL e duplicados no âmbito do time.
| Campo | Onde | Obrigatório | Descrição |
|---|---|---|---|
| url | Corpo (JSON) | Sim | URL longa (v1). |
| title | Corpo (JSON) | Não | Título do link (v1). |
Corpo (JSON)
{
"url": "https://example.com/article",
"title": "Opcional"
}Resposta de sucesso (201)
Dados do link, short_url e objeto team.
{
"success": true,
"statusCode": 201,
"data": { "slug": "…", "short_url": "…", "team": { } }
}Autenticação - REST com sessão
Envie os cookies de sessão do Supabase (como no $fetch da app com credentials: 'include'). Sem sessão válida, resposta 401.
REST /api/v1/teams (sessão)
Operações de CRUD de times, membros, convites, listagem/criação de links do time, chave API e métricas de utilização. As permissões dependem da sua função no time.
Expandir para parâmetros, query e exemplos
Criação e listagem de times
GET/api/v1/teamsLista times em que é dono ou membro aceite; inclui convites pendentes com invite_status.
Sem corpo JSON nem query string documentados para este método.
POST/api/v1/teamsCria um time; o slug é derivado do nome. Requer plano que permita criar times (ex.: Premium).
| Campo | Onde | Obrigatório | Descrição |
|---|---|---|---|
| name | Corpo (JSON) | Sim | Nome do time; o slug é derivado automaticamente. |
Notas rápidas
Corpo: { "name": "Nome do time" }
Consulta, atualização e exclusão do time
GET/api/v1/teams/:idDetalhe do time se for membro; inclui is_owner, myRole e permissions.
Sem corpo JSON nem query string documentados para este método.
PUT/api/v1/teams/:idAtualiza nome, slug e/ou settings. Requer permissão edit_team (dono ou admin).
| Campo | Onde | Obrigatório | Descrição |
|---|---|---|---|
| name | Corpo (JSON) | Não | Novo nome do time. |
| slug | Corpo (JSON) | Não | Novo slug (identificador na URL). |
| settings | Corpo (JSON) | Não | Objeto JSON de configurações do time. |
Notas rápidas
Corpo (opcional): { "name", "slug", "settings" }
DELETE/api/v1/teams/:idExclui o time. Apenas o dono (owner).
Sem corpo JSON nem query string documentados para este método.
Membros - listar, convidar, função e remoção
GET/api/v1/teams/:id/membersLista membros e estados de convite (quando aplicável).
Sem corpo JSON nem query string documentados para este método.
POST/api/v1/teams/:id/membersConvida por email (usuário cadastrado). Permissão invite_members. Roles: admin, moderator, user, viewer.
| Campo | Onde | Obrigatório | Descrição |
|---|---|---|---|
| Corpo (JSON) | Sim | Email do usuário cadastrado na plataforma. | |
| role | Corpo (JSON) | Não | admin | moderator | user | viewer (predefinido: user). |
Notas rápidas
Corpo: { "email": "…", "role?": "user" }
PUT/api/v1/teams/:id/members/:userIdAltera a função de um membro. Não aplicável ao dono do time.
| Campo | Onde | Obrigatório | Descrição |
|---|---|---|---|
| userId | Path | Sim | UUID do usuário membro. |
| role | Corpo (JSON) | Sim | admin | moderator | user | viewer. |
Notas rápidas
Corpo: { "role": "admin" | "moderator" | "user" | "viewer" }
DELETE/api/v1/teams/:id/members/:userIdRemove membro (dono/admin) ou sair do time (próprio userId). Não remove o dono.
| Campo | Onde | Obrigatório | Descrição |
|---|---|---|---|
| userId | Path | Sim | UUID do membro a remover ou o seu para sair. |
Convites - aceitar
POST/api/v1/teams/:id/accept-inviteO usuário autenticado aceita um convite pendente para esse time.
Sem corpo JSON nem query string documentados para este método.
Links do time - listar, criar, atualizar e excluir
GET/api/v1/teams/:id/linksLista links do time com paginação. Requer permissão view_links.
| Campo | Onde | Obrigatório | Descrição |
|---|---|---|---|
| page | Query | Não | Página (predefinido 1). |
| limit | Query | Não | Itens por página (máx. 50). |
| linkType | Query | Não | default | temporary (filtro). |
| disabled | Query | Não | active | disabled - filtro por estado. |
Notas rápidas
Query: page, limit (máx. 50), linkType, disabled
POST/api/v1/teams/:id/linksCria link no time. Com sessão: qualquer membro com create_link. Com chave API v1 (Bearer ou X-*): mesmo URL, corpo mínimo (url obrigatório, title opcional); o link fica associado ao dono do time.
| Campo | Onde | Obrigatório | Descrição |
|---|---|---|---|
| url | Corpo (JSON) | Sim* | URL longa. *Com chave v1: obrigatório; com sessão: obrigatório. |
| title | Corpo (JSON) | Não | Título do link. |
| linkType | Corpo (JSON) | Não | Sessão: default | temporary | premium. |
| expirationType | Corpo (JSON) | Não | Sessão, com temporary: clicks | time. |
| expiresAt | Corpo (JSON) | Não | Sessão: data ISO se expirationType=time. |
| expireAfterClicks | Corpo (JSON) | Não | Sessão: número de cliques se expirationType=clicks. |
Notas rápidas
Sessão: url (obr.), title?, linkType (default|temporary|premium), expirationType (clicks|time), expiresAt?, expireAfterClicks?. Chave v1: só url e title opcional.
PUT/api/v1/teams/:id/links/:linkIdAtualiza um link do time (o :linkId é o UUID em url_data). Sessão: permissão edit_link; mesmas validações de URL que na criação (normalização, Safe Browsing se configurado, duplicado no time exceto o próprio link) e mesma lógica de linkType/temporário/premium que no POST. Chave v1: só url e/ou title (pelo menos um campo no corpo).
| Campo | Onde | Obrigatório | Descrição |
|---|---|---|---|
| linkId | Path | Sim | UUID do link (url_data.id). |
| url | Corpo (JSON) | Não | Nova URL longa (validada como no POST). |
| title | Corpo (JSON) | Não | Novo título (vazio → título extraído da URL). |
| linkType | Corpo (JSON) | Não | Sessão: default | temporary | premium. |
| expirationType | Corpo (JSON) | Não | Sessão, com temporary: clicks | time. |
| expiresAt | Corpo (JSON) | Não | Sessão: data ISO se expirationType=time. |
| expireAfterClicks | Corpo (JSON) | Não | Sessão: cliques se expirationType=clicks. |
Notas rápidas
Sessão: campos opcionais url, title, linkType, expirationType, expiresAt, expireAfterClicks (mesmo contrato do POST). Chave v1: { url?, title? }.
DELETE/api/v1/teams/:id/links/:linkIdExclusão lógica do link do time (deleted_at). Sessão: permissão delete_link (ou dono do link). Chave v1: plano com API + chave válida; o link precisa pertencer ao time.
| Campo | Onde | Obrigatório | Descrição |
|---|---|---|---|
| linkId | Path | Sim | UUID do link (url_data.id). |
Notas rápidas
Sem corpo. Consome tokens de utilização da API v1 como as outras operações com chave.
Chave API do time - consultar, gerar e revogar
GET/api/v1/teams/:id/api-keyEstado da chave (hint, datas) e se o plano permite API. Membro do time; gestão só com edit_team.
Sem corpo JSON nem query string documentados para este método.
POST/api/v1/teams/:id/api-keyGera ou regera a chave completa (mostrada uma vez). Dono/admin + plano com API.
Sem corpo JSON nem query string documentados para este método.
DELETE/api/v1/teams/:id/api-keyRevoga a chave do time. Dono/admin.
Sem corpo JSON nem query string documentados para este método.
Utilização (painel)
GET/api/v1/teams/:id/usage-dashboardEstatísticas do time: links totais e no mês, membros, tokens API no mês e política de rate. Não inclui quota de URLs do plano pessoal do dono. Membro do time.
Sem corpo JSON nem query string documentados para este método.
Erros frequentes - Team API v1
| HTTP | Situação | Descrição |
|---|---|---|
| 400 | Pedido inválido | id em falta; corpo sem url; validação de URL; duplicado no time; etc. |
| 401 | Auth v1 | Chave em falta, Bearer inválido ou chave revogada. |
| 403 | Plano | Plano do dono sem acesso à API. |
| 404 | Time | Time não encontrado ou :id inválido. |
| 429 | Limites | Limite mensal de links do dono. |
| 500 | Servidor | Erro interno. |
Erros frequentes - REST com sessão
| HTTP | Situação | Descrição |
|---|---|---|
| 401 | Sessão | Não autenticado. |
| 403 | Permissão / plano | Sem permissão no time, limite de membros, ou plano sem API ao gerar chave. |
| 404 | Não encontrado | Time, membro ou usuário por email inexistente. |
| 409 | Conflito | Slug de time já usado; convite/migração em conflito. |
| 500 | Servidor | Erro interno. |
Exemplos cURL - Team API v1
Substitua YOUR_API_KEY e TEAM_ID. O domínio base é o da coluna de exemplos (site público).
Para /api/v1/teams com sessão, o curl precisa do cookie de sessão (copiar do navegador) ou usar o app; não é o mesmo fluxo que a chave v1.
Ping
curl -s -H "Authorization: Bearer YOUR_API_KEY" "https://encurtee.me/api/v1/teams/TEAM_ID/ping"Criar link (v1)
curl -s -X POST -H "Authorization: Bearer YOUR_API_KEY" -H "Content-Type: application/json" -d '{"url":"https://example.com/path"}' "https://encurtee.me/api/v1/teams/TEAM_ID/links"Novos endpoints serão documentados aqui à medida que forem adicionados.