> ## 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.

# Interacción con publicaciones

Una publicación de X puede recibir comentarios (respuestas), citas y retuits. Los contadores muestran los totales, pero para conocer a las personas y el contenido detrás de ellos necesitas más datos. Sorsa ofrece endpoints para obtener quién respondió y qué dijo, quién citó y qué añadió, y quién retuiteó.

Esta guía recorre desde las métricas generales hasta las respuestas, citas y perfiles individuales.

> **Nota:** consulta más análisis y flujos completos en la [guía de interacciones de Twitter](https://api.sorsa.io/blog/twitter-engagement-api).

***

## Punto de partida: métricas de una publicación

`/tweet-info` devuelve el objeto completo con todos los contadores de interacción.

### Ejemplo básico

```bash theme={null}
curl -X POST https://api.sorsa.io/v3/tweet-info \
  -H "ApiKey: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"tweet_link": "https://x.com/elonmusk/status/1234567890"}'
```

```python theme={null}
import requests

API_KEY = "YOUR_API_KEY"

def get_tweet(tweet_link):
    resp = requests.post(
        "https://api.sorsa.io/v3/tweet-info",
        headers={"ApiKey": API_KEY, "Content-Type": "application/json"},
        json={"tweet_link": tweet_link},
    )
    resp.raise_for_status()
    return resp.json()


tweet = get_tweet("https://x.com/elonmusk/status/1234567890")

print(f"Text: {tweet['full_text'][:100]}...")
print(f"Likes:    {tweet.get('likes_count', 0):,}")
print(f"Retweets: {tweet.get('retweet_count', 0):,}")
print(f"Quotes:   {tweet.get('quote_count', 0):,}")
print(f"Replies:  {tweet.get('reply_count', 0):,}")
print(f"Views:    {tweet.get('view_count', 0):,}")
print(f"Bookmarks:{tweet.get('bookmark_count', 0):,}")
```

`tweet_link` acepta una URL completa o el ID numérico de la publicación. Para varias, utiliza `/tweet-info-bulk` con hasta 100 enlaces por solicitud. Consulta [Optimización del uso de la API](https://docs.sorsa.io/es/optimizing-api-usage).

> **Consejo:** cada cuenta incluye 100 solicitudes gratuitas, sin tarjeta ni caducidad. También puedes probar estos endpoints sin código en [API Playground](https://api.sorsa.io/playground).

***

## Comentarios y respuestas

**Endpoint:** `POST /v3/comments`

Devuelve las respuestas a una publicación. Cada página contiene hasta 20 comentarios, cada uno como un objeto Tweet completo con sus métricas y autor.

### Ejemplo básico

```python theme={null}
def get_comments(tweet_link):
    resp = requests.post(
        "https://api.sorsa.io/v3/comments",
        headers={"ApiKey": API_KEY, "Content-Type": "application/json"},
        json={"tweet_link": tweet_link},
    )
    resp.raise_for_status()
    return resp.json()

data = get_comments("https://x.com/elonmusk/status/1234567890")
for comment in data.get("tweets", []):
    print(f"@{comment['user']['username']}: {comment['full_text'][:80]}")
```

### Parámetros

| Parámetro     | Tipo   | Obligatorio | Descripción                                                     |
| :------------ | :----- | :---------- | :-------------------------------------------------------------- |
| `tweet_link`  | string | Sí          | URL completa o ID de la publicación.                            |
| `order_by`    | string | No          | Orden: `"Relevance"` (predeterminado), `"Recency"` o `"Likes"`. |
| `next_cursor` | string | No          | Cursor para obtener más comentarios.                            |

Usa `"Likes"` para ordenar las respuestas por interacción en el servidor. Si solo necesitas las más destacadas, es más eficiente que recuperarlas todas y ordenarlas localmente: la primera página ya contiene las de más Me gusta.

### Recorrer todos los comentarios

Para publicaciones con cientos de respuestas, utiliza el mismo bucle de cursores que en los demás endpoints paginados:

```python theme={null}
import time

def get_all_comments(tweet_link, max_pages=20):
    """Fetch all comments under a tweet with pagination."""
    all_comments = []
    next_cursor = None

    for page in range(max_pages):
        body = {"tweet_link": tweet_link}
        if next_cursor:
            body["next_cursor"] = next_cursor

        resp = requests.post(
            "https://api.sorsa.io/v3/comments",
            headers={"ApiKey": API_KEY, "Content-Type": "application/json"},
            json=body,
        )
        resp.raise_for_status()
        data = resp.json()

        comments = data.get("tweets", [])
        all_comments.extend(comments)

        next_cursor = data.get("next_cursor")
        if not next_cursor:
            break
        time.sleep(0.1)

    return all_comments


comments = get_all_comments("https://x.com/elonmusk/status/1234567890")
print(f"Collected {len(comments)} comments")
```

Cada comentario incluye texto, métricas y perfil. Puedes ordenar por `likes_count`, buscar `?` para extraer preguntas o enviar `full_text` a un clasificador de sentimiento.

```python theme={null}
# Find the most-liked comments
top_comments = sorted(comments, key=lambda c: c.get("likes_count", 0), reverse=True)

for c in top_comments[:5]:
    print(f"@{c['user']['username']} ({c['likes_count']} likes): {c['full_text'][:80]}")
```

***

## Citas

**Endpoint:** `POST /v3/quotes`

Devuelve las publicaciones que citan otra publicación, es decir, que la comparten añadiendo un comentario. Cada cita es un Tweet completo con el texto añadido, las métricas y el autor.

### Ejemplo básico

```python theme={null}
def get_quotes(tweet_link):
    resp = requests.post(
        "https://api.sorsa.io/v3/quotes",
        headers={"ApiKey": API_KEY, "Content-Type": "application/json"},
        json={"tweet_link": tweet_link},
    )
    resp.raise_for_status()
    return resp.json()

data = get_quotes("https://x.com/elonmusk/status/1234567890")
for quote in data.get("tweets", []):
    print(f"@{quote['user']['username']} quoted: {quote['full_text'][:80]}")
```

### Parámetros

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

### Recorrer todas las citas

```python theme={null}
def get_all_quotes(tweet_link, max_pages=20):
    """Fetch all quote tweets of a specific tweet."""
    all_quotes = []
    next_cursor = None

    for page in range(max_pages):
        body = {"tweet_link": tweet_link}
        if next_cursor:
            body["next_cursor"] = next_cursor

        resp = requests.post(
            "https://api.sorsa.io/v3/quotes",
            headers={"ApiKey": API_KEY, "Content-Type": "application/json"},
            json=body,
        )
        resp.raise_for_status()
        data = resp.json()

        quotes = data.get("tweets", [])
        all_quotes.extend(quotes)

        next_cursor = data.get("next_cursor")
        if not next_cursor:
            break
        time.sleep(0.1)

    return all_quotes
```

Como cada cita incluye el perfil y el texto añadido, puedes ordenar a sus autores por audiencia:

```python theme={null}
quotes = get_all_quotes("https://x.com/brand/status/1234567890")

# Find quotes that reached the largest audiences
quotes.sort(key=lambda q: q["user"].get("followers_count", 0), reverse=True)

for q in quotes[:5]:
    u = q["user"]
    print(f"@{u['username']} ({u['followers_count']:,} followers)")
    print(f"  \"{q['full_text'][:80]}...\"\n")
```

***

## Usuarios que retuitearon

**Endpoint:** `POST /v3/retweeters`

Devuelve los **usuarios** que retuitearon una publicación, del más reciente al más antiguo. A diferencia de `/comments` y `/quotes`, utiliza `UsersResponse`, no `TweetsResponse`: recibes perfiles, no objetos de publicaciones.

### Ejemplo básico

```python theme={null}
def get_retweeters(tweet_link):
    resp = requests.post(
        "https://api.sorsa.io/v3/retweeters",
        headers={"ApiKey": API_KEY, "Content-Type": "application/json"},
        json={"tweet_link": tweet_link},
    )
    resp.raise_for_status()
    return resp.json()

data = get_retweeters("https://x.com/elonmusk/status/1234567890")
for user in data.get("users", []):
    print(f"@{user['username']} ({user['followers_count']} followers) retweeted")
```

### Parámetros

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

### Diferencia de formato

| Endpoint      | Devuelve      | Clave de respuesta | Contenido                              |
| :------------ | :------------ | :----------------- | :------------------------------------- |
| `/comments`   | Publicaciones | `tweets`           | Objetos Tweet completos: texto y autor |
| `/quotes`     | Publicaciones | `tweets`           | Objetos Tweet completos: texto y autor |
| `/retweeters` | Usuarios      | `users`            | Solo perfiles de usuario               |

Los retuits redistribuyen el original sin añadir texto propio; por eso se devuelve el perfil de quien retuiteó.

### Recorrer todos los usuarios que retuitearon

```python theme={null}
def get_all_retweeters(tweet_link, max_pages=20):
    """Fetch all users who retweeted a tweet."""
    all_users = []
    next_cursor = None

    for page in range(max_pages):
        body = {"tweet_link": tweet_link}
        if next_cursor:
            body["next_cursor"] = next_cursor

        resp = requests.post(
            "https://api.sorsa.io/v3/retweeters",
            headers={"ApiKey": API_KEY, "Content-Type": "application/json"},
            json=body,
        )
        resp.raise_for_status()
        data = resp.json()

        users = data.get("users", [])
        all_users.extend(users)

        next_cursor = data.get("next_cursor")
        if not next_cursor:
            break
        time.sleep(0.1)

    return all_users
```

Puedes sumar sus seguidores como indicador de audiencia potencial. No es alcance medido: las audiencias se solapan y seguir una cuenta no significa haber visto la publicación.

```python theme={null}
retweeters = get_all_retweeters("https://x.com/brand/status/1234567890")

total_reach = sum(u.get("followers_count", 0) for u in retweeters)
verified_count = sum(1 for u in retweeters if u.get("verified"))

print(f"Retweeters: {len(retweeters)}")
print(f"Combined follower reach: {total_reach:,}")
print(f"Verified retweeters: {verified_count}")
```

***

## Análisis completo de una publicación

Combinar los tres endpoints ofrece una visión detallada. Recorrer todas las páginas puede requerir muchas solicitudes, una por página. Reserva este proceso para publicaciones que necesiten un análisis completo:

```python theme={null}
def full_engagement_report(tweet_link):
    """Generate a complete engagement report for a single tweet."""

    tweet = get_tweet(tweet_link)
    print(f"Tweet by @{tweet['user']['username']}:")
    print(f"  \"{tweet['full_text'][:100]}...\"")
    print(f"  Likes: {tweet.get('likes_count', 0):,} | "
          f"Views: {tweet.get('view_count', 0):,}")
    print()

    comments = get_all_comments(tweet_link, max_pages=10)
    print(f"Comments: {len(comments)}")
    if comments:
        top_comment = max(comments, key=lambda c: c.get("likes_count", 0))
        print(f"  Most liked: @{top_comment['user']['username']} "
              f"({top_comment['likes_count']} likes)")
        print(f"  \"{top_comment['full_text'][:80]}...\"")
    print()

    quotes = get_all_quotes(tweet_link, max_pages=10)
    print(f"Quotes: {len(quotes)}")
    if quotes:
        biggest_quoter = max(quotes, key=lambda q: q["user"].get("followers_count", 0))
        print(f"  Highest reach: @{biggest_quoter['user']['username']} "
              f"({biggest_quoter['user']['followers_count']:,} followers)")
        print(f"  \"{biggest_quoter['full_text'][:80]}...\"")
    print()

    retweeters = get_all_retweeters(tweet_link, max_pages=10)
    total_reach = sum(u.get("followers_count", 0) for u in retweeters)
    print(f"Retweeters: {len(retweeters)}")
    print(f"  Combined reach: {total_reach:,} followers")
    if retweeters:
        top_rt = max(retweeters, key=lambda u: u.get("followers_count", 0))
        print(f"  Biggest amplifier: @{top_rt['username']} "
              f"({top_rt['followers_count']:,} followers)")

    return {
        "tweet": tweet,
        "comments": comments,
        "quotes": quotes,
        "retweeters": retweeters,
    }


report = full_engagement_report("https://x.com/brand/status/1234567890")
```

### Ejemplo de salida

```text theme={null}
Tweet by @brand:
  "We're excited to announce our Series B funding round of $50M..."
  Likes: 2,847 | Views: 892,000

Comments: 156
  Most liked: @tech_journalist (89 likes)
  "Congrats! What's the plan for international expansion?..."

Quotes: 43
  Highest reach: @vc_partner (284,000 followers)
  "This team has been on our radar for two years. Well deserved...."

Retweeters: 312
  Combined reach: 4,218,000 followers
  Biggest amplifier: @industry_leader (892,000 followers)
```

***

## Analizar varias publicaciones

Para una campaña u otro conjunto, obtén primero las publicaciones mediante `/user-tweets` o `/search-tweets` y después consulta sus interacciones:

```python theme={null}
def compare_tweet_engagement(tweet_links):
    """Compare engagement breakdown across multiple tweets."""
    results = []

    for link in tweet_links:
        tweet = get_tweet(link)
        comments = get_all_comments(link, max_pages=3)
        quotes = get_all_quotes(link, max_pages=3)
        retweeters = get_all_retweeters(link, max_pages=3)

        rt_reach = sum(u.get("followers_count", 0) for u in retweeters)

        results.append({
            "text": tweet["full_text"][:60],
            "likes": tweet.get("likes_count", 0),
            "comments": len(comments),
            "quotes": len(quotes),
            "retweets": len(retweeters),
            "retweet_reach": rt_reach,
        })
        time.sleep(0.5)

    print(f"{'Tweet':<62} {'Likes':>6} {'Cmts':>5} {'Qts':>4} {'RTs':>4} {'RT Reach':>10}")
    print("-" * 100)
    for r in results:
        print(f"{r['text']:<62} {r['likes']:>6} {r['comments']:>5} "
              f"{r['quotes']:>4} {r['retweets']:>4} {r['retweet_reach']:>10,}")

    return results
```

> **Consejo:** si solo necesitas métricas agregadas, utiliza `/tweet-info-bulk` para obtener hasta 100 publicaciones por solicitud. Consulta [Optimización del uso de la API](https://docs.sorsa.io/es/optimizing-api-usage).

***

## Exportar interacciones a CSV

```python theme={null}
import csv

def export_comments_to_csv(comments, output_file="comments.csv"):
    fields = [
        "comment_id", "created_at", "full_text", "likes", "retweets",
        "author_username", "author_followers", "author_verified",
    ]
    with open(output_file, "w", newline="", encoding="utf-8") as f:
        writer = csv.DictWriter(f, fieldnames=fields)
        writer.writeheader()
        for c in comments:
            u = c.get("user", {})
            writer.writerow({
                "comment_id": c["id"],
                "created_at": c["created_at"],
                "full_text": c["full_text"],
                "likes": c.get("likes_count", 0),
                "retweets": c.get("retweet_count", 0),
                "author_username": u.get("username", ""),
                "author_followers": u.get("followers_count", 0),
                "author_verified": u.get("verified", False),
            })
    print(f"Exported {len(comments)} comments to {output_file}")
```

El mismo patrón sirve para las citas, que también son Tweet. Para los usuarios que retuitearon, exporta campos de perfil en lugar de campos de publicación.

***

## Verificar la interacción de un usuario concreto

Sorsa dispone de endpoints específicos para verificar campañas y sorteos. `/check-retweet` puede necesitar paginación y `/check-quoted` devuelve un estado, no un booleano:

* `/check-comment`: ¿el usuario respondió?
* `/check-quoted`: ¿citó la publicación?
* `/check-retweet`: ¿la retuiteó?

Consulta [Verificación de campañas de marketing](https://docs.sorsa.io/es/Marketing-Campaign-Verification).

***

## Próximos pasos

* [Búsqueda de publicaciones](https://docs.sorsa.io/es/search-tweets): encuentra publicaciones y analiza su interacción.
* [Seguimiento de menciones](https://docs.sorsa.io/es/search-mentions): estudia las menciones más comentadas de tu marca.
* [Análisis de competidores](https://docs.sorsa.io/es/Competitor-Analysis): compara patrones de interacción.
* [Datos históricos](https://docs.sorsa.io/es/historical-data): recupera publicaciones antiguas y analiza sus resultados.
* [Verificación de campañas](https://docs.sorsa.io/es/Marketing-Campaign-Verification): comprueba acciones de usuarios concretos.
* [Referencia de la API](https://docs.sorsa.io/es/api-reference-guide): especificaciones de los endpoints de interacción y publicaciones.
