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

# Introducción

Powerstream es nuestra API de streaming en tiempo real más rápida para acceder a datos públicos de X. Al igual que la API heredada GNIP Powetrack, utiliza reglas para filtrar Publicaciones según palabras clave, operadores y metadatos. Una vez que se establece una conexión HTTP persistente con el endpoint de Powerstream, puedes empezar a recibir Publicaciones que coincidan casi en tiempo real.

Actualmente, Powerstream permite definir hasta 1.000 reglas y cada regla puede tener 2048 caracteres.

<div id="key-features">
  ## Características clave:
</div>

* **Entrega de datos en tiempo real**: Obtén datos que cumplan tus reglas casi en tiempo real.
* **Filtrado preciso**: Filtra exactamente los datos que estás buscando usando consultas booleanas con operadores.
* **Entrega**: Respuesta JSON mediante HTTP/1.1 con codificación de transferencia fragmentada (chunked transfer encoding).
* **Compatibilidad con centros de datos locales**: Obtén Publicaciones solo del centro de datos local para reducir la latencia al evitar el retardo de replicación.

<Note>
  La API de Powerstream es una oferta premium disponible en determinados planes Enterprise.

  Si estás interesado en acceder a Powerstream o en obtener más información sobre nuestras soluciones Enterprise, comunícate con nuestro equipo de ventas enviando el [Formulario de solicitud Enterprise](/es/forms/enterprise-api-interest).
  Estaremos encantados de analizar cómo Powerstream puede satisfacer tus necesidades.
</Note>

<div id="quick-start">
  ## Inicio rápido
</div>

Esta sección muestra cómo comenzar rápidamente con los endpoints de PowerStream usando Python con la biblioteca `requests`. Instálala con `pip install requests`. Todos los ejemplos usan autenticación OAuth 2.0 con Bearer Token. Reemplaza `YOUR_BEARER_TOKEN` con tu token real (almacénalo de forma segura, por ejemplo, mediante `os.getenv('BEARER_TOKEN')`).

Veremos cada endpoint con fragmentos de código. Supón que tienes estas importaciones al inicio:

```python theme={null}
import requests
import json
import time
import sys
import os  # Para vars de entorno
```

<div id="setup">
  ### Configuración
</div>

```python theme={null}
bearer_token = os.getenv('BEARER_TOKEN') or "YOUR_BEARER_TOKEN"  # Usar variable de entorno por seguridad
base_url = "https://api.x.com/2/powerstream"
rules_url = f"{base_url}/rules"  # Para la gestión de reglas
headers = {
   "Authorization": f"Bearer {bearer_token}",
   "Content-Type": "application/json"
}
```

<div id="1-create-rules-post-rules">
  ### 1. Crear reglas (POST /rules)
</div>

Añade reglas para filtrar tu stream.

```python theme={null}
data = {
   "rules": [
       {
           "value": "(cat OR dog) lang:en -is:retweet",
           "tag": "pet-monitor"
       },
       # Agrega más reglas según sea necesario (hasta 100)
   ]
}

response = requests.post(rules_url, headers=headers, json=data)
if response.status_code == 201:
   rules_added = response.json().get("data", {}).get("rules", [])
   print("Reglas agregadas:")
   for rule in rules_added:
       print(f"ID: {rule['id']}, Value: {rule['value']}, Tag: {rule.get('tag', 'N/A')}")
else:
   print(f"Error {response.status_code}: {response.text}")
```

<div id="2-delete-rules-post-rules">
  ### 2. Eliminar reglas (POST /rules)
</div>

Elimina reglas mediante id (recomendado) o por valor.

```python theme={null}
data = {
   "rules": [
       {
           "value": "(cat OR dog) lang:en -is:retweet",
           "tag": "pet-monitor"
       },
       # Agrega más reglas según sea necesario (hasta 100)
   ]
}

response = requests.delete(rules_url, headers=headers, json=data)
if response.status_code == 200:
   deleted = response.json().get("data", {})
   print(f"Deleted count: {deleted.get('deleted', 'N/A')}")
   if 'not_deleted' in deleted:
       print("Not deleted:", deleted['not_deleted'])
else:
   print(f"Error {response.status_code}: {response.text}")
```

**Consejo**: Para eliminar todas las reglas, primero obténlas con GET, extrae sus id y luego elimínalas en bloque.

<div id="3-get-rules-get-rules">
  ### 3. Obtener reglas (GET /rules)
</div>

Obtén todas las reglas activas.

```python theme={null}
response = requests.get(rules_url, headers=headers)
if response.status_code == 200:
   rules = response.json().get("data", {}).get("rules", [])
   if rules:
       print("Active rules:")
       for rule in rules:
           print(f"ID: {rule['id']}, Value: {rule['value']}, Tag: {rule.get('tag', 'N/A')}")
   else:
       print("No active rules.")
else:
   print(f"Error {response.status_code}: {response.text}")
```

<div id="4-powerstream-get-stream">
  ### 4. PowerStream (GET /stream)
</div>

Conéctate al stream para recibir Publicaciones en tiempo real. Usa `stream=True` para la lectura línea por línea. Implementa lógica de reconexión para mayor robustez.

```python theme={null}
stream_url = base_url

def main():
   while True:
       response = requests.request("GET", stream_url, headers=headers, stream=True)
       print(response.status_code)
       for response_line in response.iter_lines():
           if response_line:
               json_response = json.loads(response_line)
               print(json.dumps(json_response, indent=4, sort_keys=True))
               if response.status_code != 200:
                   print(response.headers)
                   raise Exception(
                       "Request returned an error: {} {}".format(
                           response.status_code, response.text
                       )
                   )
```

<div id="local-datacenter-support">
  #### Compatibilidad con el centro de datos local
</div>

Para optimizar la latencia, Powerstream ofrece una opción para recuperar solo las Publicaciones que se originaron o se crearon en el centro de datos local donde se establece la conexión. Esto evita la latencia de replicación, lo que resulta en una entrega más rápida en comparación con las Publicaciones de otros centros de datos. Para habilitar esto, agrega el parámetro de consulta `?localDcOnly=true` al endpoint del stream (por ejemplo, `/2/powerstream?localDcOnly=true`). El centro de datos al que estás conectado se indicará tanto en la carga inicial de datos del stream como en un encabezado HTTP en la respuesta.

Para usarlo en código:

```python theme={null}
# Solo para el centro de datos local:
stream_url = "https://api.x.com/2/powerstream?localDcOnly=true"
```

Si el parámetro `localDcOnly` está activado, cuando el stream se conecte por primera vez incluirá las siguientes cabeceras de respuesta, que indican qué centro de datos local se está utilizando:

```bash theme={null}
'x-powerstream-datacenter': 'atla',
'x-powerstream-localdconly': 'true'
```

Además, enviará una carga útil inicial que especifica el centro de datos:

```bash theme={null}
{
    "type": "connection_metadata",
    "datacenter": "atla",
    "timestamp": 1762557264155
}
```

<Note>
  **Consejo:** Para optimizar la latencia, configura conexiones desde diferentes ubicaciones geográficas (por ejemplo, una cerca de Atlanta en la costa este de EE. UU. y otra cerca de Portland en la costa oeste de EE. UU.), habilitando `localDcOnly=true` para cada una. Esto proporciona acceso más rápido a las Publicaciones desde cada centro de datos correspondiente. Agrega los streams de tu lado para combinar los datos entre centros de datos.
</Note>

<div id="operators">
  ## Operadores
</div>

Para definir reglas de filtrado, puedes usar palabras clave y operadores. Consulta la lista de operadores disponibles a continuación.

<div id="field-based-operators">
  ### Operadores por campo
</div>

<div id="user-operators">
  #### Operadores de usuario
</div>

| Operador       | Resumen                                                      | Ejemplo                            |
| -------------- | ------------------------------------------------------------ | ---------------------------------- |
| `from:`        | Coincide con publicaciones de un usuario específico          | `from:xdevelopers` o `from:123456` |
| `to:`          | Coincide con publicaciones dirigidas a un usuario específico | `to:jvaleski`                      |
| `retweets_of:` | Coincide con reposts de un usuario específico                | `retweets_of:xdevelopers`          |

<div id="content-operators">
  #### Operadores de contenido
</div>

| Operador        | Descripción                                                                 | Ejemplo                                 |
| --------------- | --------------------------------------------------------------------------- | --------------------------------------- |
| `contains:`     | Coincide con Publicaciones que contienen texto o palabras clave específicas | `contains:hello` o `contains:-2345.432` |
| `url_contains:` | Coincide con Publicaciones con URL que contienen texto específico           | `url_contains:"com/willplayforfood"`    |
| `lang:`         | Coincide con Publicaciones en idiomas específicos                           | `lang:en`                               |

<div id="entity-operators">
  #### Operadores de entidades
</div>

| Operador | Resumen                                                                                                                           | Ejemplo                                 |
| -------- | --------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------- |
| `has:`   | Devuelve publicaciones que contienen entidades específicas (opciones: mentions, geo, links, media, lang, symbols, images, videos) | `has:images`, `has:geo`, `has:mentions` |
| `is:`    | Devuelve publicaciones de tipos específicos o con propiedades específicas (opciones: retweet, reply)                              | `is:retweet`, `is:reply`                |

<div id="location-operators">
  #### Operadores de ubicación
</div>

| Operador        | Descripción                                                            | Ejemplo                                                                                  |
| --------------- | ---------------------------------------------------------------------- | ---------------------------------------------------------------------------------------- |
| `place:`        | Coincide con publicaciones de lugares o ubicaciones específicos        | `place:"Belmont Central"`, `place:02763fa2a7611cf3`                                      |
| `bounding_box:` | Coincide con publicaciones dentro de un recuadro geográfico delimitado | `bounding_box:[-112.424083 42.355283 -112.409111 42.792311]`                             |
| `point_radius:` | Coincide con publicaciones dentro de un radio con centro en un punto   | `point_radius:[-111.464973 46.371179 25mi]`, `point_radius:[-111.464973 46.371179 15km]` |

<div id="advancedcontent-operators">
  #### Operadores avanzados/de contenido
</div>

| Operator    | Summary                                                                                                                          | Example |
| ----------- | -------------------------------------------------------------------------------------------------------------------------------- | ------- |
| `bio:`      | Coincide con Publicaciones de usuarios cuyo perfil incluye un contenido de biografía específico (utiliza coincidencia de frases) | N/D     |
| `bio_name:` | Coincide con Publicaciones de usuarios cuyo perfil incluye un nombre específico en la biografía (utiliza coincidencia de frases) | N/D     |

<div id="additional-operators">
  #### Operadores adicionales
</div>

| Operador                 | Resumen                                                   | Ejemplo                                     |
| ------------------------ | --------------------------------------------------------- | ------------------------------------------- |
| `retweets_of_status_id:` | Coincide con republicaciones de publicaciones específicas | `retweets_of_status_id:1234567890123456789` |
| `in_reply_to_status_id:` | Coincide con respuestas a publicaciones específicas       | `in_reply_to_status_id:1234567890123456789` |

<div id="non-field-operators">
  ### Operadores no basados en campos
</div>

<div id="special-syntax-operators">
  #### Operadores de sintaxis especial
</div>

| Operador               | Resumen                     | Ejemplo          |
| ---------------------- | --------------------------- | ---------------- |
| `@`                    | Operador de mención         | `@username`      |
| Coincidencia de frases | Coincide con frases exactas | `"exact phrase"` |

<div id="logical-operators">
  #### Operadores lógicos
</div>

| Operador    | Descripción                           | Ejemplo                                             |
| ----------- | ------------------------------------- | --------------------------------------------------- |
| `OR`        | OR lógico entre expresiones           | `x OR facebook`                                     |
| Espacio/AND | AND lógico entre expresiones          | `x facebook` (ambos términos deben estar presentes) |
| `()`        | Agrupación para expresiones complejas | `(x OR facebook) iphone`                            |
| `-`         | Negación/exclusión                    | `x -facebook` (x pero no facebook)                  |

<div id="responses">
  ## Respuestas
</div>

La carga útil de la API Powestream tiene el mismo formato que la API PowerTrack heredada de GNIP. Un ejemplo de respuesta JSON es el siguiente:

```json theme={null}
[
   {
       "created_at": "Tue Mar 21 20:50:14 +0000 2006",
       "id": 20,
       "id_str": "20",
       "text": "just setting up my twttr",
       "truncated": false,
       "entities": {
           "hashtags": [],
           "symbols": [],
           "user_mentions": [],
           "urls": []
       },
       "source": "<a href=\"http://x.com\" rel=\"nofollow\">X Web Client</a>",
       "in_reply_to_status_id": null,
       "in_reply_to_status_id_str": null,
       "in_reply_to_user_id": null,
       "in_reply_to_user_id_str": null,
       "in_reply_to_screen_name": null,
       "user": {
           "id": 12,
           "id_str": "12",
           "name": "jack",
           "screen_name": "jack",
           "location": "",
           "description": "no state is the best state",
           "url": "https://t.co/ZEpOg6rn5L",
           "entities": {
               "url": {
                   "urls": [
                       {
                           "url": "https://t.co/ZEpOg6rn5L",
                           "expanded_url": "http://primal.net/jack",
                           "display_url": "primal.net/jack",
                           "indices": [
                               0,
                               23
                           ]
                       }
                   ]
               },
               "description": {
                   "urls": []
               }
           },
           "protected": false,
           "followers_count": 6427829,
           "friends_count": 3,
           "listed_count": 32968,
           "created_at": "Tue Mar 21 20:50:14 +0000 2006",
           "favourites_count": 36306,
           "utc_offset": null,
           "time_zone": null,
           "geo_enabled": true,
           "verified": false,
           "statuses_count": 30134,
           "lang": null,
           "contributors_enabled": false,
           "is_translator": false,
           "is_translation_enabled": false,
           "profile_background_color": "EBEBEB",
           "profile_background_image_url": "http://abs.twimg.com/images/themes/theme7/bg.gif",
           "profile_background_image_url_https": "https://abs.twimg.com/images/themes/theme7/bg.gif",
           "profile_background_tile": false,
           "profile_image_url": "http://pbs.twimg.com/profile_images/1661201415899951105/azNjKOSH_normal.jpg",
           "profile_image_url_https": "https://pbs.twimg.com/profile_images/1661201415899951105/azNjKOSH_normal.jpg",
           "profile_banner_url": "https://pbs.twimg.com/profile_banners/12/1742427520",
           "profile_link_color": "990000",
           "profile_sidebar_border_color": "DFDFDF",
           "profile_sidebar_fill_color": "F3F3F3",
           "profile_text_color": "333333",
           "profile_use_background_image": true,
           "has_extended_profile": true,
           "default_profile": false,
           "default_profile_image": false,
           "following": null,
           "follow_request_sent": null,
           "notifications": null,
           "translator_type": "regular",
           "withheld_in_countries": []
       },
       "geo": null,
       "coordinates": null,
       "place": null,
       "contributors": null,
       "is_quote_status": false,
       "retweet_count": 122086,
       "favorite_count": 263321,
       "favorited": false,
       "retweeted": false,
       "lang": "en"
   }
]
```

<div id="limits-best-practices">
  ## Límites y mejores prácticas
</div>

* Límites de tasa: 50 solicitudes/24 h para la gestión de reglas; sin límite en streams (pero se aplican límites de conexión).
* Reconexión: backoff exponencial en caso de desconexión.
* Monitoreo: usa encabezados `Connection: keep-alive`.
