Visão geral da API
A API do Zynko é a mesma que os apps usam: HTTP com JSON para ler e mudar as coisas, e um gateway WebSocket para receber o que acontece em tempo real. Um bot usa as duas com o token dele.
| Base da API | https://zynko.org/api |
| Gateway | wss://zynko.org/api/gateway |
| Formato | JSON (UTF-8), exceto envio de arquivos (multipart/form-data) |
Todas as rotas desta referência são relativas à base. GET /users/@me quer dizer GET https://zynko.org/api/users/@me.
Autenticação
Mande o token no cabeçalho Authorization:
http
GET /api/users/@me HTTP/1.1
Host: zynko.org
Authorization: Bot bot_3f9a...e1O servidor aceita os prefixos Bot e Bearer do mesmo jeito. Tokens de bot começam com bot_ seguido de 64 dígitos hexadecimais e não expiram: valem até o dono gerar um novo (POST /users/@me/bots/{bot_id}/token) ou apagar o bot. Quando isso acontece, as conexões abertas no gateway com o token antigo caem com o código 4000.
Sem token, ou com um token inválido, as rotas respondem 401 unauthorized. Algumas coisas são só para pessoas (criar servidor, entrar por convite, criar bots, fazer amizade); nessas um bot recebe 403 ou 400. A lista de rotas marca cada uma.
IDs
Todo id (usuário, servidor, canal, mensagem, cargo, emoji, anexo) é um snowflake de 64 bits e viaja como string no JSON, porque não cabe num number do JavaScript sem perder precisão:
json
{ "id": "1234567890123456789", "channel_id": "1234567890123456000" }No corpo das requisições o servidor aceita ids como string ou como número, mas mande string. Nos caminhos (/channels/{channel_id}) eles vão como número decimal.
Um snowflake guarda o momento em que foi criado: os 42 bits de cima são milissegundos desde 2026-01-01T00:00:00Z (1767225600000 em Unix ms), e os 22 de baixo são uma sequência. Ordenar por id é ordenar por criação.
js
const EPOCH = 1767225600000n;
const criadoEm = (id) => new Date(Number((BigInt(id) >> 22n) + EPOCH));
criadoEm(msg.id); // Date de quando a mensagem foi enviadaO contrário também funciona: (BigInt(ms) - EPOCH) << 22n é o menor id possível naquele instante, útil para paginar mensagens a partir de uma data (?after=).
Datas e outros valores
- Datas são números: milissegundos desde a época Unix (
timestamp,edited_timestamp,joined_at,expires_at,since,created_at). - Permissões são números (bits; cabem em 18 bits). Veja Permissões.
- Cores de cargo são inteiros
0xRRGGBBounull; a cor de destaque do perfil é uma string"#rrggbb". - Rotas que só confirmam algo respondem
{ "ok": true }.
Erros
Os erros da API têm sempre o mesmo formato:
json
{ "code": "forbidden", "message": "Você não tem permissão para isso" }message é uma frase em português pronta para mostrar a uma pessoa; programe contra code e o status HTTP.
| Status | code | Quando |
|---|---|---|
| 400 | bad_request | Dado inválido ou ação impossível (nome longo demais, mensagem vazia, canal errado...). |
| 401 | unauthorized | Sem token, ou token inválido. |
| 403 | forbidden | Falta permissão, ou a rota é só para pessoas. |
| 403 | email_unverified | Login de uma conta com e-mail não confirmado. Não acontece com bots. |
| 404 | not_found | Não existe ou você não tem acesso. |
| 409 | conflict | Nome já em uso (por exemplo o username de um bot novo). |
| 413 | too_large | Arquivo grande demais. |
| 429 | rate_limited | Limite de requisições estourado. |
| 429 | slow_mode | O modo lento do canal ainda não deixou mandar de novo. |
| 500 | internal | Erro do servidor. |
| 503 | unavailable | Recurso não configurado neste servidor (arquivos, voz). |
404 em vez de 403
Para que não dê para sondar ids, um servidor de que você não é membro, ou um canal que você não pode ver, responde 404, como se não existisse. 403 aparece quando você vê a coisa mas não pode fazer aquilo com ela.
Erros que o servidor nem chega a processar não seguem esse formato: um JSON malformado, um corpo sem Content-Type: application/json ou um id inválido no caminho voltam com 400, 415 ou 422 e uma mensagem em texto puro.
Limites de requisição (429)
Quando um limite estoura, a resposta é 429 com o tempo de espera em milissegundos no corpo e em segundos no cabeçalho Retry-After:
http
HTTP/1.1 429 Too Many Requests
Retry-After: 4
{ "code": "rate_limited", "message": "Calma! Você está indo rápido demais", "retry_after_ms": 3712 }O modo lento de um canal responde do mesmo jeito, com code: "slow_mode".
Os limites são contados por conta (o bot inteiro, não por canal), em janelas fixas. Os que importam para um bot:
| Ação | Rota | Limite |
|---|---|---|
| Enviar mensagem | POST /channels/{id}/messages | 10 a cada 10 s |
| Editar mensagem | PATCH /channels/{id}/messages/{id} | 10 a cada 10 s |
| Reagir | PUT .../reactions/{emoji} | 20 a cada 10 s |
| Digitando | POST /channels/{id}/typing | 10 a cada 10 s |
| Enviar anexo | POST /channels/{id}/attachments | 30 por minuto |
| Enviar imagem (avatar, ícone, emoji) | POST /media | 10 por minuto |
| Criar postagem em fórum | POST /channels/{id}/posts | 10 por minuto |
| Editar perfil | PATCH /users/@me | 20 por minuto |
| Criar convite | POST /guilds/{id}/invites | 20 por hora |
| Entrar numa sala de voz | POST /channels/{id}/voice | 20 por minuto |
| Trocar o servidor de voz da sala | PUT /channels/{id}/voice/server | 10 por minuto |
Apagar mensagens, tirar reações e as rotas de gerenciamento não têm limite próprio.
Além disso, cada canal pode ter modo lento (rate_limit_per_user, em segundos): depois de mandar uma mensagem (ou abrir uma postagem), a mesma conta espera esse tempo antes da próxima. Quem tem Gerenciar mensagens ou Gerenciar canais no canal não espera.
Imagens e arquivos
Os campos de imagem (avatar, banner, icon, url de emoji) guardam um destes:
- um caminho relativo do próprio Zynko,
/api/media/{id}/{segredo}: público, sem autenticação, com cache longo. Para usar, junte com a origem:https://zynko.org/api/media/...; - uma URL absoluta de GIF do KLIPY (
https://static.klipy.com/...), usada como está.
js
const urlDaImagem = (v) => (v?.startsWith('/') ? 'https://zynko.org' + v : v);Para trocar uma imagem, envie o arquivo em POST /media (PNG, JPEG, GIF, WebP ou AVIF, até 16 MB), pegue o id que volta e mande-o como avatar_id, banner_id, icon_id ou image_id na rota que usa a imagem. Uploads que não forem usados somem em um dia.
Anexos de mensagens são outra coisa. Cada canal tem sua chave e os arquivos ficam cifrados; o url de um anexo é /api/attachments/{id} e só quem pode ver o canal consegue baixar, mandando o token. Qualquer outra pessoa recebe 404. Os downloads aceitam Range. Tipos que o navegador pode exibir (imagens, vídeo e áudio comuns) vêm com o Content-Type original; o resto vem como application/octet-stream.
- Vídeos podem ter uma miniatura em
/api/attachments/{id}/thumb(campothumbnail). - Emojis do servidor também estão em
/api/emojis/{id}, que redireciona para a imagem, sem autenticação. - Imagens de prévias de links (
embeds[].image.url) passam por/api/embeds/image?....
Veja Arquivos para os detalhes do envio.
Texto das mensagens
O conteúdo é texto com marcação no estilo do Discord. Menções e emojis do servidor ficam dentro do texto:
| Escreva | Para |
|---|---|
<@ID_DO_USUARIO> | mencionar alguém (a pessoa recebe notificação) |
<:nome:ID_DO_EMOJI> | um emoji do servidor |
<a:nome:ID_DO_EMOJI> | um emoji animado do servidor |
Não há lista separada de menções na mensagem: procure <@id> no content.
Próximos passos
- Gateway: conectar e receber eventos.
- Eventos: tudo o que chega pelo gateway.
- Rotas: todas as rotas que um bot pode usar.
- Objetos: os formatos JSON.
- Permissões: os bits, os cargos e os canais.