> ## 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 y comunidades

Utiliza Sorsa API para obtener miembros, seguidores y publicaciones de listas públicas de X. Esta página también describe los formatos de los endpoints de comunidades; consulta la nota de disponibilidad antes de utilizarlos en un flujo nuevo.

> **Nota:** consulta estrategia, costes y flujos completos en la [guía de listas de X](https://api.sorsa.io/blog/x-lists-and-communities-api).

> **Disponibilidad de comunidades:** la referencia incluye estos endpoints, pero es necesario confirmar la disponibilidad actual de sus datos. Antes de desarrollar un flujo nuevo, [contacta con soporte](https://docs.sorsa.io/es/support) para confirmar operaciones y resultados disponibles. Los ejemplos siguientes documentan la interfaz; no constituyen una prueba de disponibilidad en vivo.

***

## Listas

Una lista pública de X agrupa hasta 5.000 cuentas. Tiene dos audiencias:

* **Miembros:** cuentas añadidas por quien gestiona la lista.
* **Seguidores o suscriptores:** usuarios que se suscriben a su cronología.

La API no accede a listas privadas.

| Endpoint             | Método | Devuelve                                              | Tamaño de página |
| :------------------- | :----- | :---------------------------------------------------- | :--------------- |
| `/v3/list-members`   | GET    | Perfiles de cuentas incluidas en la lista             | Hasta 200        |
| `/v3/list-followers` | GET    | Perfiles de sus seguidores                            | Hasta 200        |
| `/v3/list-tweets`    | GET    | Publicaciones cronológicas combinadas de sus miembros | Unas 20          |

El ID es el número de la URL: en `https://x.com/i/lists/1234567890` es `1234567890`.

> **Consejo:** las 100 solicitudes gratuitas de cada cuenta, sin tarjeta ni caducidad, permiten recuperar una lista de tamaño medio. Prueba los endpoints sin código en [API Playground](https://api.sorsa.io/playground).

### Obtener miembros

`GET /v3/list-members`

| Parámetro     | Tipo   | Obligatorio | Descripción                       |
| :------------ | :----- | :---------- | :-------------------------------- |
| `list_id`     | string | Sí          | ID numérico de la lista.          |
| `next_cursor` | string | No          | Cursor de una respuesta 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)")
```

Una lista de 5.000 miembros requiere unas 25 solicitudes.

### Obtener seguidores

`GET /v3/list-followers`

| Parámetro     | Tipo   | Obligatorio | Descripción                    |
| :------------ | :----- | :---------- | :----------------------------- |
| `list_link`   | string | Sí          | URL o ID numérico de la lista. |
| `next_cursor` | string | No          | Cursor de paginación.          |

Atención al nombre: `/list-followers` acepta `list_link` (URL o ID), mientras que `/list-members` y `/list-tweets` aceptan `list_id`, solo el ID 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")
```

### Obtener publicaciones

`GET /v3/list-tweets`

Devuelve publicaciones recientes de todos los miembros en un feed cronológico. Se utiliza en [Supervisión en tiempo real](https://docs.sorsa.io/es/real-time-monitoring) para seguir grupos con una sola solicitud en lugar de consultar cada cuenta.

| Parámetro     | Tipo   | Obligatorio | Descripción              |
| :------------ | :----- | :---------- | :----------------------- |
| `list_id`     | string | Sí          | ID numérico de la lista. |
| `next_cursor` | string | No          | Cursor de paginación.    |

```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

Estos formatos describen los endpoints de la referencia. Confirma su disponibilidad como se indica al principio antes de depender de ellos.

La pertenencia a una comunidad puede ayudar a descubrir audiencias cuando los datos están disponibles, pero no demuestra actividad reciente.

| Endpoint                      | Método | Devuelve                                           | Tamaño de página |
| :---------------------------- | :----- | :------------------------------------------------- | :--------------- |
| `/v3/community-members`       | POST   | Perfiles de miembros                               | Unos 20          |
| `/v3/community-tweets`        | POST   | Publicaciones de la comunidad                      | Unas 20          |
| `/v3/community-search-tweets` | POST   | Búsqueda por palabras clave dentro de la comunidad | Unas 20          |

El ID es el número de su URL: en `https://x.com/i/communities/1966045657589813686` es `1966045657589813686`.

Las comunidades privadas no eran accesibles mediante API.

### Obtener miembros

`POST /v3/community-members`

| Parámetro        | Tipo   | Obligatorio | Descripción                        |
| :--------------- | :----- | :---------- | :--------------------------------- |
| `community_link` | string | Sí          | ID o URL completa de la comunidad. |
| `next_cursor`    | string | No          | Cursor de paginación.              |

Devuelve perfiles compactos: ID, nombre de usuario, nombre público, avatar y estados de verificación y protección.

```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
```

### Obtener publicaciones

`POST /v3/community-tweets`

| Parámetro      | Tipo   | Obligatorio | Descripción                                |
| :------------- | :----- | :---------- | :----------------------------------------- |
| `community_id` | string | Sí          | ID numérico de la comunidad.               |
| `order`        | string | No          | `"latest"` (predeterminado) o `"popular"`. |
| `next_cursor`  | string | No          | Cursor de paginación.                      |

```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
```

### Buscar publicaciones

`POST /v3/community-search-tweets`

| Parámetro        | Tipo   | Obligatorio | Descripción                                             |
| :--------------- | :----- | :---------- | :------------------------------------------------------ |
| `community_link` | string | Sí          | ID o URL completa.                                      |
| `query`          | string | No          | Palabra clave. Omítela para consultar el feed completo. |
| `order`          | string | No          | `"popular"` o `"latest"`.                               |
| `next_cursor`    | string | No          | Cursor de paginación.                                   |

```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 comprobar la pertenencia de un usuario sin recorrer toda la lista, utiliza [`/check-community-member`](https://docs.sorsa.io/es/api-reference/verificaci%C3%B3n/comprobar-pertenencia-a-una-comunidad).

***

## Exportar a CSV

Puedes exportar usuarios y publicaciones de listas con una función auxiliar. Para usuarios:

```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` y `/list-followers` devuelven perfiles en `users`; `/list-tweets` devuelve publicaciones en `tweets`, con el autor en `user`. Los campos opcionales pueden estar vacíos. Al exportar publicaciones, aplana los valores anidados explícitamente, por ejemplo `{"username": tweet["user"]["username"]}`. Un escritor CSV no resuelve rutas como `user.username`.

***

## Guías relacionadas

* [Guía de listas de X](https://api.sorsa.io/blog/x-lists-and-communities-api): estrategia, costes y casos de uso.
* [Supervisión en tiempo real](https://docs.sorsa.io/es/real-time-monitoring): consultas periódicas de `/list-tweets`.
* [Descubrimiento del público objetivo](https://docs.sorsa.io/es/target-audiences-Discovery): investigación de audiencias con listas.
* [Verificación de campañas](https://docs.sorsa.io/es/Marketing-Campaign-Verification): comprobaciones de pertenencia.
* [Optimización del uso de la API](https://docs.sorsa.io/es/optimizing-api-usage): lotes y límites de frecuencia.
