> ## Documentation Index
> Fetch the complete documentation index at: https://docs.x.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Início rápido

> Este guia orienta você na configuração de um app consumidor de webhook, implementando o. Referência para a X API v2 standard tier cobrindo webhooks.

Este guia orienta você na configuração de um app consumidor de webhook, na implementação do Challenge-Response Check (CRC), na proteção de eventos recebidos e no registro do seu webhook no X.

## 1. Desenvolver um app consumidor de webhook

Para registrar um webhook no seu X app, você precisa desenvolver, implantar e hospedar um web app que receba eventos de webhook do X e responda às requisições de segurança CRC.

### Requisitos de URL

Crie um web app com uma URL HTTPS publicamente acessível que atuará como o endpoint de webhook para receber eventos:

* O **path** do URI é sua escolha. Estes exemplos são todos válidos:
  * `https://mydomain.com/service/listen`
  * `https://mydomain.com/webhook/twitter`
* A URL **não pode** incluir uma especificação de porta (por exemplo, `https://mydomain.com:5000/webhook` **não** funcionará)

### O que seu app precisa lidar

Seu endpoint de webhook deve lidar com dois tipos de requisições HTTP:

| Tipo de requisição | Propósito                                                                     |
| :----------------- | :---------------------------------------------------------------------------- |
| **GET**            | [Validação CRC](#2-the-crc-check) — O X verifica que você controla o endpoint |
| **POST**           | Entrega de eventos — O X envia payloads JSON dos eventos                      |

***

## 2. O CRC check

O Challenge-Response Check (CRC) é como o X valida que a URL de callback que você forneceu é válida e que **você a controla**. Seu web app deve responder corretamente às requisições de CRC para registrar e manter seu webhook.

### Quando o CRC é acionado

| Gatilho                | Descrição                                          |
| :--------------------- | :------------------------------------------------- |
| **Registro inicial**   | Quando você chama `POST /2/webhooks`               |
| **Validação horária**  | O X valida automaticamente seu webhook a cada hora |
| **Revalidação manual** | Quando você chama `PUT /2/webhooks/:webhook_id`    |

Se o seu webhook falhar em um CRC check, ele será marcado como `invalid` e **parará de receber eventos** até que passe novamente.

### Como o CRC funciona

Quando o X envia um CRC, ele faz uma **requisição GET** para sua URL de webhook com um parâmetro de consulta `crc_token`:

```
GET https://your-webhook-url.com/webhook?crc_token=challenge_string
```

Sua aplicação deve responder com um corpo JSON contendo um `response_token`:

```json theme={null}
{
  "response_token": "sha256=<base64_encoded_hmac_hash>"
}
```

### Como construir a resposta do CRC

1. Use o valor de `crc_token` do parâmetro de consulta como a **mensagem**
2. Use o **consumer secret** (API secret key) do seu app como a **chave**
3. Crie um hash **HMAC SHA-256**
4. Faça o **Base64 encode** do resultado
5. Adicione `sha256=` como prefixo à string codificada

<Warning>
  **Importante:** Seu web app deve usar o **consumer secret** (API secret key) do seu app para a criptografia CRC — não seu bearer token ou access token.
</Warning>

### Exemplo: Python

```python title="Exemplo" lines wrap icon="python" theme={null}
import hmac
import hashlib
import base64

def handle_crc(crc_token, consumer_secret):
    """
    Respond to a Twitter CRC check.
    
    Args:
        crc_token: The crc_token query parameter from the GET request
        consumer_secret: Your app's consumer secret (API secret key)
    
    Returns:
        dict with the response_token
    """
    sha256_hash = hmac.new(
        consumer_secret.encode('utf-8'),
        crc_token.encode('utf-8'),
        hashlib.sha256
    ).digest()

    return {
        "response_token": "sha256=" + base64.b64encode(sha256_hash).decode('utf-8')
    }
```

### Exemplo: Node.js

```javascript title="Exemplo" lines wrap icon="square-js" theme={null}
const crypto = require('crypto');

function handleCrc(crcToken, consumerSecret) {
  const hmac = crypto
    .createHmac('sha256', consumerSecret)
    .update(crcToken)
    .digest('base64');

  return {
    response_token: `sha256=${hmac}`
  };
}
```

### Exemplo: Flask (endpoint completo)

Este exemplo mostra um endpoint de webhook completo que lida com a validação CRC (GET) e a entrega de eventos (POST):

```python title="Exemplo" expandable lines wrap icon="python" theme={null}
from flask import Flask, request, jsonify
import hmac
import hashlib
import base64

app = Flask(__name__)

CONSUMER_SECRET = "your_consumer_secret_here"

@app.route("/webhook", methods=["GET", "POST"])
def webhook():
    if request.method == "GET":
        # Handle CRC check
        crc_token = request.args.get("crc_token")
        if crc_token:
            sha256_hash = hmac.new(
                CONSUMER_SECRET.encode("utf-8"),
                crc_token.encode("utf-8"),
                hashlib.sha256,
            ).digest()
            response_token = "sha256=" + base64.b64encode(sha256_hash).decode("utf-8")
            return jsonify({"response_token": response_token}), 200
        return "Missing crc_token", 400

    elif request.method == "POST":
        # Handle incoming webhook events
        event = request.get_json()
        print("Received event:", event)
        return "", 200
```

***

## 3. Protegendo webhooks

As APIs baseadas em webhook do X fornecem dois métodos para confirmar a segurança do seu servidor de webhook:

### Challenge-Response Check (CRC)

O CRC permite que o X confirme a propriedade do web app que recebe eventos de webhook. Consulte a [Etapa 2](#2-the-crc-check) acima para detalhes completos de implementação.

### Verificação de assinatura

Cada requisição POST do X inclui um header `x-twitter-webhooks-signature` que permite confirmar que o X é a origem do webhook recebido.

Para verificar a assinatura:

1. Obtenha o valor do header `x-twitter-webhooks-signature` da requisição recebida
2. Crie um hash HMAC SHA-256 usando seu **consumer secret** como chave e o **corpo bruto da requisição** como mensagem
3. Faça o Base64 encode do hash e adicione `sha256=` como prefixo
4. Compare o valor calculado com o valor do header — eles devem coincidir

```python title="Exemplo" expandable lines wrap icon="python" theme={null}
import hmac
import hashlib
import base64

def verify_signature(payload, signature_header, consumer_secret):
    """
    Verify that a webhook POST request actually came from X.
    
    Args:
        payload: The raw request body (bytes)
        signature_header: The x-twitter-webhooks-signature header value
        consumer_secret: Your app's consumer secret
    
    Returns:
        True if the signature is valid
    """
    expected = "sha256=" + base64.b64encode(
        hmac.new(
            consumer_secret.encode("utf-8"),
            payload,
            hashlib.sha256
        ).digest()
    ).decode("utf-8")
    
    return hmac.compare_digest(expected, signature_header)
```

***

## 4. Registrar seu webhook

Assim que seu app puder lidar com CRC checks, registre a URL do seu webhook fazendo uma requisição `POST /2/webhooks`. Quando você fizer essa requisição, o X enviará imediatamente uma requisição CRC para o seu web app para verificar a propriedade.

Todos os endpoints de gerenciamento de webhook requerem autenticação com **OAuth2 App Only Bearer Token**.

### Criar um webhook

**`POST /2/webhooks`** — [Referência da API](/x-api/webhooks/create-webhook)

```bash theme={null}
curl --request POST \
  --url 'https://api.x.com/2/webhooks' \
  --header 'Authorization: Bearer $BEARER_TOKEN' \
  --header 'Content-Type: application/json' \
  --data '{
    "url": "https://yourdomain.com/webhooks/twitter"
  }'
```

**Resposta de sucesso (200 OK):**

Uma resposta bem-sucedida indica que o webhook foi criado e que o CRC check inicial passou.

```json theme={null}
{
  "data": {
    "id": "1234567890",
    "url": "https://yourdomain.com/webhooks/twitter",
    "valid": true,
    "created_at": "2025-01-15T12:00:00.000Z"
  }
}
```

Quando um webhook é registrado com sucesso, a resposta inclui um **webhook ID**. Esse ID é necessário ao fazer requisições a produtos que suportam webhooks (por exemplo, vincular ao Filtered Stream ou criar subscriptions para o Account Activity).

**Motivos comuns de falha:**

| Motivo                 | Descrição                                                                                              |
| :--------------------- | :----------------------------------------------------------------------------------------------------- |
| `CrcValidationFailed`  | Sua URL de callback não respondeu corretamente ao CRC check (por exemplo, timeout, resposta incorreta) |
| `UrlValidationFailed`  | A URL de callback não atende aos requisitos (por exemplo, não é `https`, formato inválido)             |
| `DuplicateUrlFailed`   | Já existe um webhook registrado por sua aplicação para esta URL                                        |
| `WebhookLimitExceeded` | Sua aplicação atingiu o número máximo de webhooks permitidos                                           |

### Visualizar webhooks

**`GET /2/webhooks`** — [Referência da API](/x-api/webhooks/get-webhook)

Recupere todas as configurações de webhook associadas à sua aplicação.

```bash theme={null}
curl --request GET \
  --url 'https://api.x.com/2/webhooks' \
  --header 'Authorization: Bearer $BEARER_TOKEN'
```

**Resposta (com um webhook):**

```json title="Exemplo de resposta" lines wrap icon="https://mintcdn.com/x-preview/Vn2KEkZaPF9LiPi3/icons/xds/icon-brackets.svg?fit=max&auto=format&n=Vn2KEkZaPF9LiPi3&q=85&s=ed2428e77bab43e57800e1a590e982fa" theme={null}
{
  "data": [
    {
      "created_at": "2025-01-15T12:00:00.000Z",
      "id": "1234567890",
      "url": "https://yourdomain.com/webhooks/twitter",
      "valid": true
    }
  ],
  "meta": {
    "result_count": 1
  }
}
```

**Resposta (sem webhooks):**

```json theme={null}
{
  "data": [],
  "meta": {
    "result_count": 0
  }
}
```

### Excluir um webhook

**`DELETE /2/webhooks/:webhook_id`** — [Referência da API](/x-api/webhooks/delete-webhook)

Exclua um webhook usando seu `webhook_id` (obtido na resposta de criação ou listagem).

```bash theme={null}
curl --request DELETE \
  --url 'https://api.x.com/2/webhooks/1234567890' \
  --header 'Authorization: Bearer $BEARER_TOKEN'
```

**Resposta:**

```json theme={null}
{
  "data": {
    "deleted": true
  }
}
```

| Motivo da falha    | Descrição                                                                    |
| :----------------- | :--------------------------------------------------------------------------- |
| `WebhookIdInvalid` | O `webhook_id` fornecido não foi encontrado ou não está associado ao seu app |

### Validar e reativar um webhook

**`PUT /2/webhooks/:webhook_id`** — [Referência da API](/x-api/webhooks/validate-webhook)

Aciona um CRC check para o webhook informado. Se o check for bem-sucedido, o webhook é reativado com `valid: true`.

```bash theme={null}
curl --request PUT \
  --url 'https://api.x.com/2/webhooks/1234567890' \
  --header 'Authorization: Bearer $BEARER_TOKEN'
```

**Resposta:**

Uma resposta 200 OK indica que o CRC check foi iniciado. O campo `valid` reflete o status após a tentativa de check. Você pode verificar o status atual usando `GET /2/webhooks`.

```json theme={null}
{
  "data": {
    "valid": true
  }
}
```

| Motivo da falha       | Descrição                                                                    |
| :-------------------- | :--------------------------------------------------------------------------- |
| `WebhookIdInvalid`    | O `webhook_id` fornecido não foi encontrado ou não está associado ao seu app |
| `CrcValidationFailed` | A URL de callback não respondeu corretamente ao CRC check                    |

***

## Testes com xurl

Para fins de teste, a ferramenta `xurl` suporta webhooks temporários. Instale a versão mais recente do [projeto `xurl`](https://github.com/xdevplatform/xurl) do GitHub, configure sua autorização e depois execute:

```bash theme={null}
xurl webhook start
```

Isso gerará uma URL de webhook pública temporária, lidará automaticamente com todos os CRC checks e registrará quaisquer eventos de subscription recebidos. É uma ótima maneira de verificar sua configuração antes de fazer o deploy. Exemplo de saída:

```
Starting webhook server with ngrok...
Enter your ngrok authtoken (leave empty to try NGROK_AUTHTOKEN env var):

Attempting to use NGROK_AUTHTOKEN environment variable for ngrok authentication.
Configuring ngrok to forward to local port: 8080
Ngrok tunnel established!
  Forwarding URL: https://<your-ngrok-subdomain>.ngrok-free.app -> localhost:8080

Use this URL for your X API webhook registration: https://<your-ngrok-subdomain>.ngrok-free.app/webhook

Starting local HTTP server to handle requests from ngrok tunnel...
```

***

## Notas importantes

<Warning>
  * **Todas as Direct Messages recebidas** serão entregues via webhooks. DMs enviadas via [POST /2/dm\_conversations/with/:participant\_id/messages](/x-api/direct-messages/send-a-new-message-to-a-user) também serão entregues, para que seu app possa acompanhar DMs enviadas por outros clientes.

  * Se você tiver **mais de um web app** compartilhando a mesma URL de webhook e o mesmo usuário mapeado para cada app, o mesmo evento será enviado para o seu webhook **várias vezes** (uma por web app).

  * Em alguns casos, seu webhook pode receber **eventos duplicados**. Seu app de webhook deve tolerar isso e **desduplicar pelo ID do evento**.

  * O X envia eventos como requisições **POST** com payloads JSON. Consulte a [estrutura do objeto de dados do Account Activity](/x-api/account-activity/introduction#account-activity-data-object-structure) para exemplos de payloads.
</Warning>

***

## Apps de exemplo

| App                                                                                                                    | Descrição                                                                                                               |
| :--------------------------------------------------------------------------------------------------------------------- | :---------------------------------------------------------------------------------------------------------------------- |
| [Servidor de webhook simples](https://github.com/m-rosinsky/XWebhookTest/blob/main/app.py)                             | Um único script Python que mostra como responder ao CRC check e aceitar eventos POST                                    |
| [Dashboard da Account Activity API](https://github.com/xdevplatform/account-activity-dashboard-enterprise/tree/master) | Um web app escrito com [bun.sh](https://bun.sh) que permite gerenciar webhooks, subscriptions e receber eventos ao vivo |
| [Ferramenta de teste xurl](https://github.com/xdevplatform/xurl)                                                       | Ferramenta CLI para testes temporários de webhook — lida automaticamente com CRC checks e registra eventos              |

***

## Próximos passos

<CardGroup cols={2}>
  <Card title="Filtered Stream Webhooks" icon="https://mintcdn.com/x-preview/szd6PKNMlRQoyyAo/icons/xds/icon-filter.svg?fit=max&auto=format&n=szd6PKNMlRQoyyAo&q=85&s=5d59aff402c1f2aeae0e9e44bb23400e" href="/x-api/webhooks/stream/introduction" width="24" height="24" data-path="icons/xds/icon-filter.svg">
    Receba Posts filtrados via webhook
  </Card>

  <Card title="Account Activity API" icon="https://mintcdn.com/x-preview/Vn2KEkZaPF9LiPi3/icons/xds/icon-bell.svg?fit=max&auto=format&n=Vn2KEkZaPF9LiPi3&q=85&s=5e0b3dcfbb39ba3d4619931d7cd927d1" href="/x-api/account-activity/introduction" width="24" height="24" data-path="icons/xds/icon-bell.svg">
    Receba eventos de conta via webhook
  </Card>
</CardGroup>
