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

# Listas e comunidades

Obtenha membros, seguidores e publicações de listas públicas do X. Esta página também documenta os formatos de requisição de comunidades; confirme a disponibilidade antes de usá-los em novos fluxos.

> Veja estratégias, custos e monitoramento no [guia de listas do X](https://api.sorsa.io/blog/x-lists-and-communities-api).

> **Disponibilidade de comunidades:** os endpoints constam na referência, mas a disponibilidade atual dos dados precisa ser confirmada. Consulte o [suporte](https://docs.sorsa.io/pt-BR/support) sobre operações e resultados disponíveis. Os exemplos documentam a interface e não são testes de disponibilidade em produção.

## Listas

Uma lista pública reúne até 5.000 contas. **Membros** são as contas adicionadas pelo curador; **seguidores da lista** são quem assinou sua timeline. Listas privadas não estão acessíveis pela API.

| Endpoint             | Método | Retorna                      | Página  |
| :------------------- | :----- | :--------------------------- | :------ |
| `/v3/list-members`   | GET    | Perfis dos membros           | Até 200 |
| `/v3/list-followers` | GET    | Perfis de quem segue a lista | Até 200 |
| `/v3/list-tweets`    | GET    | Feed cronológico combinado   | \~20    |

O ID é o número na URL: em `https://x.com/i/lists/1234567890`, é `1234567890`.

> Cada conta começa com 100 requisições gratuitas, sem cartão nem validade. Teste no [API Playground](https://api.sorsa.io/playground).

### Membros da lista

`GET /v3/list-members`

| Parâmetro     | Tipo   | Obrigatório | Descrição                    |
| :------------ | :----- | :---------- | :--------------------------- |
| `list_id`     | string | Sim         | ID numérico da lista.        |
| `next_cursor` | string | Não         | Cursor da resposta anterior. |

```bash theme={null}
curl "https://api.sorsa.io/v3/list-members?list_id=1234567890" \
  -H "ApiKey: YOUR_API_KEY"
```

```python theme={null}
import requests

API_KEY = "YOUR_API_KEY"
BASE = "https://api.sorsa.io/v3"
HEADERS = {"ApiKey": API_KEY}


def get_list_members(list_id, max_pages=50):
    members, cursor = [], None

    for _ in range(max_pages):
        params = {"list_id": list_id}
        if cursor:
            params["next_cursor"] = cursor

        r = requests.get(f"{BASE}/list-members", headers=HEADERS, params=params, timeout=30)
        r.raise_for_status()
        data = r.json()

        members.extend(data.get("users", []))
        cursor = data.get("next_cursor")
        if not cursor:
            break

    return members


members = get_list_members("1234567890")
for u in members[:5]:
    print(f"@{u['username']} ({u['followers_count']:,} followers)")
```

Uma lista com 5.000 membros exige cerca de 25 chamadas.

### Seguidores da lista

`GET /v3/list-followers`

| Parâmetro     | Tipo   | Obrigatório | Descrição           |
| :------------ | :----- | :---------- | :------------------ |
| `list_link`   | string | Sim         | URL ou ID da lista. |
| `next_cursor` | string | Não         | Cursor.             |

Atenção: este endpoint usa `list_link` (URL ou ID); `/list-members` e `/list-tweets` usam `list_id`, apenas numérico.

```python theme={null}
def get_list_followers(list_link, max_pages=50):
    followers, cursor = [], None

    for _ in range(max_pages):
        params = {"list_link": list_link}
        if cursor:
            params["next_cursor"] = cursor

        r = requests.get(f"{BASE}/list-followers", headers=HEADERS, params=params, timeout=30)
        r.raise_for_status()
        data = r.json()

        followers.extend(data.get("users", []))
        cursor = data.get("next_cursor")
        if not cursor:
            break

    return followers


subs = get_list_followers("https://x.com/i/lists/1234567890")
print(f"{len(subs)} subscribers")
```

### Publicações da lista

`GET /v3/list-tweets`

Feed recente de todos os membros, usado no [monitoramento em tempo real](https://docs.sorsa.io/pt-BR/real-time-monitoring) para consultar várias contas em uma chamada.

| Parâmetro     | Tipo   | Obrigatório | Descrição             |
| :------------ | :----- | :---------- | :-------------------- |
| `list_id`     | string | Sim         | ID numérico da lista. |
| `next_cursor` | string | Não         | Cursor.               |

```python theme={null}
def get_list_tweets(list_id, max_pages=10):
    tweets, cursor = [], None

    for _ in range(max_pages):
        params = {"list_id": list_id}
        if cursor:
            params["next_cursor"] = cursor

        r = requests.get(f"{BASE}/list-tweets", headers=HEADERS, params=params, timeout=30)
        r.raise_for_status()
        data = r.json()

        tweets.extend(data.get("tweets", []))
        cursor = data.get("next_cursor")
        if not cursor:
            break

    return tweets


feed = get_list_tweets("1234567890", max_pages=10)
for t in feed[:5]:
    print(f"@{t['user']['username']}: {t['full_text'][:80]}")
```

## Comunidades

Confirme a disponibilidade conforme a nota acima. Participação pode indicar interesse, mas não comprova atividade recente.

| Endpoint                      | Método | Retorna                    | Página |
| :---------------------------- | :----- | :------------------------- | :----- |
| `/v3/community-members`       | POST   | Perfis dos membros         | \~20   |
| `/v3/community-tweets`        | POST   | Publicações da comunidade  | \~20   |
| `/v3/community-search-tweets` | POST   | Busca dentro da comunidade | \~20   |

O ID é o número da URL: em `https://x.com/i/communities/1966045657589813686`, é `1966045657589813686`. Comunidades privadas não eram acessíveis pela API.

### Membros da comunidade

`POST /v3/community-members`

| Parâmetro        | Tipo   | Obrigatório | Descrição           |
| :--------------- | :----- | :---------- | :------------------ |
| `community_link` | string | Sim         | ID ou URL completa. |
| `next_cursor`    | string | Não         | Cursor.             |

Retorna perfis compactos com ID, nome de usuário, nome público, avatar, verificação e status protegido.

```python theme={null}
def get_community_members(community_link, max_pages=20):
    members, cursor = [], None

    for _ in range(max_pages):
        body = {"community_link": community_link}
        if cursor:
            body["next_cursor"] = cursor

        r = requests.post(
            f"{BASE}/community-members",
            headers={**HEADERS, "Content-Type": "application/json"},
            json=body,
            timeout=30,
        )
        r.raise_for_status()
        data = r.json()

        members.extend(data.get("users", []))
        cursor = data.get("next_cursor")
        if not cursor:
            break

    return members
```

### Publicações da comunidade

`POST /v3/community-tweets`

| Parâmetro      | Tipo   | Obrigatório | Descrição                           |
| :------------- | :----- | :---------- | :---------------------------------- |
| `community_id` | string | Sim         | ID numérico.                        |
| `order`        | string | Não         | `"latest"` (padrão) ou `"popular"`. |
| `next_cursor`  | string | Não         | Cursor.                             |

```python theme={null}
def get_community_tweets(community_id, order="latest", max_pages=10):
    tweets, cursor = [], None

    for _ in range(max_pages):
        body = {"community_id": community_id, "order": order}
        if cursor:
            body["next_cursor"] = cursor

        r = requests.post(
            f"{BASE}/community-tweets",
            headers={**HEADERS, "Content-Type": "application/json"},
            json=body,
            timeout=30,
        )
        r.raise_for_status()
        data = r.json()

        tweets.extend(data.get("tweets", []))
        cursor = data.get("next_cursor")
        if not cursor:
            break

    return tweets
```

### Busca na comunidade

`POST /v3/community-search-tweets`

| Parâmetro        | Tipo   | Obrigatório | Descrição                                  |
| :--------------- | :----- | :---------- | :----------------------------------------- |
| `community_link` | string | Sim         | ID ou URL completa.                        |
| `query`          | string | Não         | Palavra-chave; omita para o feed completo. |
| `order`          | string | Não         | `"popular"` ou `"latest"`.                 |
| `next_cursor`    | string | Não         | Cursor.                                    |

```python theme={null}
def search_community_tweets(community_link, query, order="popular", max_pages=5):
    tweets, cursor = [], None

    for _ in range(max_pages):
        body = {"community_link": community_link, "query": query, "order": order}
        if cursor:
            body["next_cursor"] = cursor

        r = requests.post(
            f"{BASE}/community-search-tweets",
            headers={**HEADERS, "Content-Type": "application/json"},
            json=body,
            timeout=30,
        )
        r.raise_for_status()
        data = r.json()

        tweets.extend(data.get("tweets", []))
        cursor = data.get("next_cursor")
        if not cursor:
            break

    return tweets
```

Para verificar um membro específico sem percorrer toda a lista, use [`/check-community-member`](https://docs.sorsa.io/pt-br/api-reference/verifica%C3%A7%C3%A3o/verificar-participa%C3%A7%C3%A3o-na-comunidade).

## Exportar para CSV

Exemplo para perfis de usuários:

```python theme={null}
import csv

def export_users_to_csv(users, path):
    fields = ["id", "username", "display_name", "description",
              "followers_count", "tweets_count", "verified", "location"]

    with open(path, "w", newline="", encoding="utf-8") as f:
        writer = csv.DictWriter(f, fieldnames=fields)
        writer.writeheader()
        for u in users:
            writer.writerow({
                "id": u.get("id", ""),
                "username": u.get("username", ""),
                "display_name": u.get("display_name", ""),
                "description": (u.get("description") or "").replace("\n", " "),
                "followers_count": u.get("followers_count", 0),
                "tweets_count": u.get("tweets_count", 0),
                "verified": u.get("verified", False),
                "location": u.get("location", ""),
            })


export_users_to_csv(get_list_members("1234567890"), "members.csv")
```

`/list-members` e `/list-followers` retornam `users`; `/list-tweets` retorna `tweets`, com autor em `user`. Campos opcionais podem estar vazios. Ao exportar publicações, extraia explicitamente campos aninhados, como `{"username": tweet["user"]["username"]}`. O gravador CSV não resolve `user.username` automaticamente.

## Relacionados

* [Guia de listas](https://api.sorsa.io/blog/x-lists-and-communities-api): estratégia e custos.
* [Monitoramento](https://docs.sorsa.io/pt-BR/real-time-monitoring): polling de listas.
* [Público-alvo](https://docs.sorsa.io/pt-BR/target-audiences-Discovery): pesquisa de audiência.
* [Campanhas](https://docs.sorsa.io/pt-BR/Marketing-Campaign-Verification): verificar participação.
* [Otimização](https://docs.sorsa.io/pt-BR/optimizing-api-usage): lotes e limites.
