Interações

Receba comandos, cliques e modais pelo Gateway ou webhook e responda.

Uma interação nasce quando alguém usa um slash command, clica num botão ou menu, ou envia um modal aberto pelo seu bot. Ela precisa ser respondida em até 15 minutos; depois disso expira.

Tipos de interação

kindOrigemCampos extras
commandSlash commandcommand: { id, name, options }
componentClique em botão / escolha em menumessageId, customId, componentValues (array de strings nos menus, senão null)
modal_submitEnvio de um modalmessageId, customId (do modal), componentValues = { [custom_id]: valor }
INTERACTION_CREATE
{
  "id": "uuid-da-interacao",
  "kind": "command",
  "command": { "id": "…", "name": "sauda", "options": { "quem": "mundo" } },
  "serverId": "…",
  "channelId": "…",
  "invokingUserId": "…"
}

Como chegam ao bot

O modo é definido na aplicação: sem URL configurada = Gateway; com URL = webhook.

Modo Gateway (padrão)

O evento INTERACTION_CREATE chega no socket do bot. Requer o intent interactions.receive.

Atenção
Não há fila: se o bot estiver desconectado no momento, a interação não é entregue e expira em 15 minutos.

Modo webhook

O NEX faz POST na sua URL HTTPS a cada interação, com User-Agent: NexBotWebhook/1.0 e os cabeçalhos de assinatura:

Cabeçalhos
X-Nex-Timestamp: 1759672800
X-Nex-Signature: sha256=<hex>
X-Nex-Signature-Previous: sha256=<hex>   // só na 1ª hora após rotacionar o segredo

A assinatura é um HMAC-SHA256 de `${timestamp}.${corpo}` com o segredo de assinatura da aplicação. Aceite se qualquer uma das duas bater.

Verificando (Node.js)
const crypto = require('crypto');

function assinaturaValida(rawBody, timestamp, header, segredo) {
  if (!header) return false;
  const esperado = 'sha256=' + crypto.createHmac('sha256', segredo)
    .update(`${timestamp}.${rawBody}`).digest('hex');
  const a = Buffer.from(header), b = Buffer.from(esperado);
  return a.length === b.length && crypto.timingSafeEqual(a, b);
}
Regra de entregaValor
Tempo limite por tentativa3 s
Tentativas3 (imediata, +2 s, +8 s) em erro de rede ou 5xx
Resposta 4xxnão tenta de novo; a interação expira
Redirecionamentosnão são seguidos
Corpo da sua respostaaté 64 KB

Você pode responder no próprio corpo do 200 (um JSON com type, igual ao do /respond) ou devolver qualquer outro 2xx e responder depois pela API.

Limitação atual
No webhook, interações command chegam como command: { id, name }, sem options. Comandos com argumentos precisam do modo Gateway.

Para testar a URL, use o botão do portal: ele envia { "type": "PING" } assinado.

Responder

POST/api/bot/interactions/:id/respond
Auth: BotResponde { "ok": true }. Só a primeira resposta final vale.
Corpo
{ "type": 4, "content": "…", "embeds": [], "components": [], "flags": 0 }
typeNomeParaEfeito
4CHANNEL_MESSAGE_WITH_SOURCEtodosEnvia uma mensagem no canal. Com flags: 64 (efêmera), só quem interagiu vê.
5DEFERRED_CHANNEL_MESSAGE_WITH_SOURCEtodosMostra "pensando…" para quem interagiu. Responda de novo na mesma interação em até 15 min.
6DEFERRED_UPDATE_MESSAGEcomponent, modal_submitReconhece sem efeito visível.
7UPDATE_MESSAGEcomponent, modal_submitEdita a mensagem original (mesmas regras do PATCH). Só se a mensagem for da sua aplicação.
9MODALcommand, componentAbre um formulário. É final: não dá para responder de novo.

O formato antigo { "content": "…" } continua funcionando (vira tipo 4). Efêmeras (flag 64) não valem para os tipos 6, 7 e 9.

ErroMotivo
400Corpo inválido para o tipo de resposta (a mensagem diz o campo).
403Tipo 7 em mensagem de outra aplicação.
404Interação não existe ou é de outra aplicação.
409Interação já respondida ou expirada.

Modais

Resposta tipo 9
{
  "type": 9,
  "modal": {
    "title": "Fale conosco",           // 1–45
    "custom_id": "contato",            // 1–100
    "components": [                    // 1–5 Labels
      {
        "type": 18, "label": "Seu nome", "description": "opcional, até 100",
        "component": { "type": 4, "custom_id": "nome", "style": 1, "required": true, "min_length": 2, "max_length": 50 }
      }
    ]
  }
}

Text Input (type: 4): style 1 (linha) ou 2 (parágrafo), min_length 0–4000, max_length 1–4000, value e placeholder (100) opcionais, required padrão true. Quando a pessoa envia, sua aplicação recebe uma nova interação modal_submit.