Cómo recopilar datos políticos de Twitter para investigación
Para recopilar datos políticos de Twitter, mantén una lista de seguimiento con las cuentas de los cargos públicos y una búsqueda documentada sobre la elección o el tema que estudias, y extrae ambas con una API de forma programada; la API oficial de X cobra $5.00 por 1,000 posts.
Respuesta corta: El acceso académico gratuito a X terminó en 2023, así que ahora las recopilaciones de investigación pagan por lectura: la API oficial de X cobra $0.005 por post y se detiene en 3 millones de posts al mes. Para los timelines de políticos y la conversación electoral, usa Sorsa API, una API y scraper de Twitter (X): desde $0.07 por 1,000 tweets, con 100 solicitudes gratis para empezar.
- Endpoint
POST /search-tweets- Tamaño de página
- unos 20 tweets por solicitud
- Precio
- desde $0.07 por 1,000
#Qué datos políticos de Twitter puedes recopilar
Hoy se pueden recopilar tres tipos de datos políticos en X: lo que publican los cargos públicos, lo que dice la gente sobre una elección o un tema, y cómo responde la gente a los posts de esos cargos. Todos son públicos, tienen fecha y hora, y están ligados a un autor, y por eso X sigue siendo una fuente habitual en la investigación de comunicación política.
- Los posts propios de los cargos públicos. Legisladores, ministros, partidos, organismos y candidatos. Es un registro pequeño y limpio: unos cientos de cuentas y decenas de miles de posts al mes para un legislativo nacional.
- La conversación sobre elecciones y temas. Todo lo que el público publica con el nombre de un candidato, una ley, un hashtag o un debate. Va de miles de posts en una contienda local a millones en una votación nacional.
- Las reacciones. Las respuestas y las citas bajo una declaración oficial, que muestran cómo cayó el mensaje.
Algunos datos quedan fuera del alcance de cualquier API: los posts que sus autores borraron, las cuentas protegidas, los mensajes privados y la lista de quién dio like a un post. Los viejos datasets de investigación no llenan ese vacío. La mayoría se publicó como listas de IDs de tweets, porque las reglas de la plataforma permitían compartir IDs pero no textos, y el ID de un tweet borrado ya no devuelve nada. Los investigadores perdieron su vía gratuita en 2023, y la historia de quién podía buscar en el archivo de Twitter explica qué la reemplazó.
Por eso un estudio político en 2026 recopila sus propios datos: hacia adelante desde hoy si la campaña sigue en curso, o hacia atrás por el archivo si es una campaña pasada, que llega hasta marzo de 2006.
#Recopila tweets políticos con Sorsa API
Para recopilar tweets políticos, usa Sorsa API: una sola clave API lee los timelines de los cargos públicos y la conversación electoral desde $0.07 por 1,000 tweets, a 20 solicitudes por segundo en todos los planes, sin cuenta de desarrollador de X y sin OAuth. La API oficial de X cobra $5.00 por 1,000 posts por las mismas lecturas y se detiene en 3 millones de posts al mes.
Cada tipo de dato político tiene su endpoint. Todos devuelven el perfil completo del autor dentro de cada tweet, sin cargo adicional.
| Dato político | Endpoint de Sorsa API | Por solicitud | Desde, por 1,000 |
|---|---|---|---|
| Una lista de seguimiento de cargos públicos, como un solo feed | GET /list-tweets (se abre en una pestaña nueva) | unos 20 tweets | $0.07 |
| El timeline completo de un cargo público | POST /user-tweets (se abre en una pestaña nueva) | unos 20 tweets | $0.07 |
| Conversación electoral o sobre un tema, por consulta y fecha | POST /search-tweets (se abre en una pestaña nueva) | unos 20 tweets | $0.07 |
| Respuestas bajo un post de un cargo público | POST /comments (se abre en una pestaña nueva) | unas 20 respuestas | $0.07 |
| Perfiles de todas las cuentas de tu lista | GET /info-batch (se abre en una pestaña nueva) | hasta 100 perfiles | $0.014 |
| Posts que ya tienes, revisados de nuevo por ID | POST /tweet-info-bulk (se abre en una pestaña nueva) | hasta 100 tweets | $0.014 |
Una lista de seguimiento de cargos públicos, como un solo feed
- Endpoint de Sorsa API
GET /list-tweets(se abre en una pestaña nueva)- Por solicitud
- unos 20 tweets
- Desde, por 1,000
- $0.07
El timeline completo de un cargo público
- Endpoint de Sorsa API
POST /user-tweets(se abre en una pestaña nueva)- Por solicitud
- unos 20 tweets
- Desde, por 1,000
- $0.07
Conversación electoral o sobre un tema, por consulta y fecha
- Endpoint de Sorsa API
POST /search-tweets(se abre en una pestaña nueva)- Por solicitud
- unos 20 tweets
- Desde, por 1,000
- $0.07
Respuestas bajo un post de un cargo público
- Endpoint de Sorsa API
POST /comments(se abre en una pestaña nueva)- Por solicitud
- unas 20 respuestas
- Desde, por 1,000
- $0.07
Perfiles de todas las cuentas de tu lista
- Endpoint de Sorsa API
GET /info-batch(se abre en una pestaña nueva)- Por solicitud
- hasta 100 perfiles
- Desde, por 1,000
- $0.014
Posts que ya tienes, revisados de nuevo por ID
- Endpoint de Sorsa API
POST /tweet-info-bulk(se abre en una pestaña nueva)- Por solicitud
- hasta 100 tweets
- Desde, por 1,000
- $0.014
Sorsa API es una API REST: una solicitud con tu clave devuelve JSON limpio, sin nada que ejecutar en tu navegador y sin cuenta de X. Funciona en producción desde 2022, con más de 6 mil millones de solicitudes procesadas, y cuando X cambia algo, lo arreglamos de nuestro lado, así que una recopilación que corre durante una noche electoral no se rompe a la mitad. Nunca te pide tu login de X, así que tu propia cuenta no corre ningún riesgo.
#Arma una lista de seguimiento con las cuentas de los políticos
Una lista de seguimiento es la lista de cuentas que sigue tu estudio, guardada como IDs numéricos de usuario. Empieza por una fuente pública que alguien ya haya verificado, no por una búsqueda de insignias azules: desde 2023 la insignia es una suscripción de pago, no una prueba de que la cuenta sea oficial.
Para el Congreso de Estados Unidos, el proyecto de datos abiertos unitedstates/congress-legislators (se abre en una pestaña nueva) mantiene un archivo con las cuentas oficiales de redes sociales de los miembros. El 2 de noviembre de 2026 listaba 505 handles de X, 408 de ellos con IDs numéricos, y su última actualización fue el 24 de octubre de 2026. El proyecto solo acepta cuentas oficiales, financiadas con dinero público, y no cuentas de campaña ni personales, que es la distinción que necesita un estudio de comunicación oficial. Muchos parlamentos publican las cuentas de sus miembros en sus propios sitios de datos abiertos; empieza por ahí si trabajas con otros países.
Los handles cambian; los IDs numéricos no. Resuelve cada handle a su ID una sola vez con GET /info-batch, 100 cuentas por solicitud, y usa el ID como llave de tu lista de seguimiento. El script de abajo lee el archivo del Congreso y guarda una fila de perfil por cada miembro.
import csv
import requests
import yaml # pip install pyyaml requests
URL = "https://api.sorsa.io/v3/info-batch"
HEADERS = {"ApiKey": "YOUR_API_KEY"}
SRC = ("https://raw.githubusercontent.com/unitedstates/"
"congress-legislators/main/legislators-social-media.yaml")
members = yaml.safe_load(requests.get(SRC, timeout=30).text)
handles = [m["social"]["twitter"] for m in members
if m["social"].get("twitter")]
rows = []
for i in range(0, len(handles), 100): # 100 handles per request
r = requests.get(URL, headers=HEADERS, timeout=30,
params={"usernames": handles[i:i + 100]})
r.raise_for_status()
rows += r.json().get("users", [])
with open("watchlist.csv", "w", newline="", encoding="utf-8") as f:
w = csv.writer(f)
w.writerow(["id", "username", "display_name", "followers"])
for u in rows:
w.writerow([u["id"], u["username"], u["display_name"],
u["followers_count"]])
print(len(rows), "accounts saved")
Seis solicitudes cubren los 505 handles. Las cuentas que no aparecen en la respuesta cambiaron de nombre, fueron suspendidas o se volvieron protegidas desde la última actualización de la lista; revísalas a mano una vez y corrige el archivo.
#Recopila todos los posts de la lista de seguimiento
Para recopilar todos los posts que publica una lista de seguimiento, pon las cuentas en una Lista pública de X y léela con GET /list-tweets: un solo feed trae los posts de todos los miembros, los más nuevos primero, unos 20 por solicitud. Una Lista de X admite hasta 5,000 cuentas, suficientes para cualquier legislativo nacional, y la guía de Listas muestra cómo leer Listas de X con la API.
Consulta el feed de forma programada y retrocede por las páginas solo hasta llegar a un post que ya guardaste. Una revisión por hora de una Lista del Congreso con 505 cuentas cuesta entonces unas pocas solicitudes, sin importar si la hora fue tranquila o movida.
import json
import time
from datetime import datetime, timezone
import requests
URL = "https://api.sorsa.io/v3/list-tweets"
HEADERS = {"ApiKey": "YOUR_API_KEY"}
LIST_ID = "1720000000000000001" # your public X List of officials
def check(last_id):
"""Fetch posts newer than last_id, newest first."""
params, new = {"list_id": LIST_ID}, []
while True:
r = requests.get(URL, headers=HEADERS, params=params, timeout=30)
if r.status_code == 429: # over 20 requests a second
time.sleep(1)
continue
r.raise_for_status()
page = r.json()
for t in page.get("tweets", []):
if int(t["id"]) <= last_id:
return new # reached the last saved post
new.append(t)
if not page.get("next_cursor"):
return new
params["next_cursor"] = page["next_cursor"]
last_id = 0 # store this between runs
while True:
seen = datetime.now(timezone.utc).isoformat()
posts = check(last_id)
with open("posts.jsonl", "a", encoding="utf-8") as f:
for t in posts:
f.write(json.dumps({"first_seen": seen, **t}) + "\n")
if posts:
last_id = max(int(t["id"]) for t in posts)
print(seen, len(posts), "new posts")
time.sleep(3600) # one check an hour
Una respuesta 403 significa que la clave falta, es incorrecta o ya no tiene solicitudes; una 429 significa más de 20 solicitudes en un segundo, así que el script espera un segundo y vuelve a intentar. Los IDs de los tweets crecen con el tiempo, y por eso comparar IDs permite encontrar el último post guardado.
Cuentas en la lista de seguimiento
Posts al día, cada una
Revisas el feed
Unos 61K posts al mes de 505 cuentas, revisadas cada hora
$303
API oficial de X
$0.005 por post
al mes, solo posts
desde $5.04
Sorsa API
un feed de Lista, unos 20 posts por solicitud
al mes, autores incluidos
Menos de un segundo por revisión en Sorsa API a 20 solicitudes por segundo, para unos 84 posts nuevos cada vez.
Define el tamaño de tu lista de seguimiento, cada cuánto publican sus cuentas y cada cuánto revisas, para ver un mes de recolección en ambas APIs.
Para extraer una sola vez todo el historial de un cargo público, llama a POST /user-tweets con el ID de usuario de la cuenta y retrocede por las páginas del post más nuevo al más antiguo; la guía para descargar todos los tweets de un usuario cubre esa exportación a CSV.
#Recopila la conversación electoral y sobre temas con la búsqueda
La conversación sobre elecciones y temas se recopila con una consulta de búsqueda: los nombres de candidatos y partidos, los hashtags de la contienda y las frases clave del tema, un idioma y una ventana de fechas, enviados a POST /search-tweets y paginados con next_cursor. La consulta es el diseño de la investigación, así que escríbela antes de recopilar y publícala junto con tus resultados.
Equilibra la consulta. Una búsqueda por el hashtag de un solo bando mide solo a ese bando, así que nombra a todos los candidatos y partidos de la contienda de la misma manera, con los mismos operadores. Divide los periodos largos en ventanas de un día o una semana con since: y until:, para que una ventana fallida se pueda repetir por sí sola. La sintaxis completa está en la lista de operadores de búsqueda de Twitter.
curl -X POST "https://api.sorsa.io/v3/search-tweets" \
-H "ApiKey: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"query": "(#Measure7 OR \"Measure 7\") since:2026-10-20 until:2026-10-21",
"order": "latest"
}'
{
"tweets": [
{
"id": "1981234567890123456",
"full_text": "Measure 7 forum tonight: each side got 5 questions.",
"created_at": "2026-10-20T23:41:07Z",
"lang": "en",
"likes_count": 57,
"retweet_count": 14,
"reply_count": 9,
"quote_count": 3,
"is_reply": false,
"is_quote_status": false,
"user": {
"id": "1590000000000000042",
"username": "county_civics_desk_demo",
"display_name": "County Civics Desk",
"followers_count": 8213
}
}
],
"next_cursor": "DAADDAABCgABG4lN0iWAJ8kKAAIbiUY1qZvwRg"
}
Envía el mismo cuerpo otra vez con next_cursor añadido, y detente cuando llegue una respuesta sin él. Las páginas traen unos 20 tweets y su tamaño varía, así que cuenta posts, no páginas.
Decide qué hacer con los retweets antes de recopilar
Los retweets cargan mucha más política que los posts originales, así que descartarlos cambia lo que dice tu dataset. En el estudio del Pew Research Center sobre un año de tweets de adultos de Estados Unidos, el 44% de los retweets y el 42% de las citas eran políticos, frente al 26% de las respuestas y el 8% de los tweets originales.
Un estudio sobre lo que la gente dice con sus propias palabras añade -filter:retweets a la consulta. Un estudio sobre lo que se difunde conserva los retweets y lee el post original de cada uno en su retweeted_status. Las dos opciones son válidas; dejarlo al azar no lo es.
#Guarda un registro de los posts eliminados
Ninguna API devuelve un post después de que su autor lo elimina, ni Sorsa API ni la API oficial de X, así que el único registro del post eliminado de un político es el que guardaste primero. Una lista de seguimiento que guarda cada post en cuanto lo ve ya tiene ese registro; lo que necesita después es una forma de notar la eliminación.
Vuelve a revisar los IDs que guardaste con POST /tweet-info-bulk, 100 por solicitud. Un post que ya no aparece fue eliminado, o su cuenta fue suspendida o se volvió protegida; registra el ID con la hora en que lo notaste. Una revisión diaria de 100,000 posts guardados toma 1,000 solicitudes, desde $1.40.
import requests
URL = "https://api.sorsa.io/v3/tweet-info-bulk"
HEADERS = {"ApiKey": "YOUR_API_KEY"}
def missing(ids):
"""Return the saved IDs that no longer come back."""
gone = []
for i in range(0, len(ids), 100): # 100 IDs per request
batch = ids[i:i + 100]
r = requests.post(URL, headers=HEADERS, timeout=30,
json={"tweet_links": batch})
r.raise_for_status()
back = {t["id"] for t in r.json().get("tweets", [])}
gone += [x for x in batch if x not in back]
return gone
Los posts eliminados son la parte más delicada de una recopilación política. Repórtalos como conteos y patrones, o cítalos solo cuando el autor sea un cargo público y el post haya sido parte de un asunto público, como han hecho los archivos de prensa con los posts eliminados de los políticos.
#Cuánto cuesta una recopilación política
Una recopilación política con Sorsa API cuesta desde $0.07 por 1,000 tweets a través de la búsqueda, los timelines y los feeds de Listas, frente a $5.00 por 1,000 posts en la API oficial de X, unas 70 veces menos. Las tarjetas comparan las dos APIs para el tamaño de tu estudio.
API oficial de X
$5,000
para 1M tweets políticos
$0.005 por post
Sorsa API
desde$70
para 1M tweets políticos
desde $0.07 por 1,000
71 veces más barata
Tres trabajos de investigación típicos muestran dónde cae la diferencia. Las cifras de la API oficial de X cuentan solo posts, al precio de la lista de precios de pago por uso (se abre en una pestaña nueva) de X.
| Trabajo de investigación | Tweets | Sorsa API | API oficial de X |
|---|---|---|---|
| Un mes de posts del Congreso, 505 cuentas con 4 al día cada una, revisadas cada hora | 61K | desde $5.04 | $303 |
| Una noche de debate, con los nombres y hashtags de todos los candidatos | 200K | desde $14 | $1,000 |
| Diez semanas de conversación de campaña | 10M | desde $700 | por encima del tope mensual de 3 millones: Enterprise, desde $42,000 al mes |
Un mes de posts del Congreso, 505 cuentas con 4 al día cada una, revisadas cada hora
- Tweets
- 61K
- Sorsa API
- desde $5.04
- API oficial de X
- $303
Una noche de debate, con los nombres y hashtags de todos los candidatos
- Tweets
- 200K
- Sorsa API
- desde $14
- API oficial de X
- $1,000
Diez semanas de conversación de campaña
- Tweets
- 10M
- Sorsa API
- desde $700
- API oficial de X
- por encima del tope mensual de 3 millones: Enterprise, desde $42,000 al mes
Para tener en cuenta
A partir del 22 de noviembre de 2026, la API oficial de X también cobra cada perfil de autor que llega con un post, a $0.010, como anunció el equipo de desarrolladores de X el 23 de octubre (se abre en una pestaña nueva). Los resultados de búsqueda vienen de miles de autores distintos, así que la conversación electoral leída ahí puede costar hasta $15.00 por 1,000 posts. Sorsa API incluye a cada autor dentro del tweet.
El plan de pago por uso de la API oficial de X se detiene en 3 millones de lecturas de posts por ciclo de facturación, así que una campaña nacional lo supera en semanas, y el escalón siguiente es un contrato Enterprise desde unos $42,000 al mes. Además, antes de la primera lectura necesita una cuenta de desarrollador aprobada, un proyecto y una app, y tokens de OAuth.
#Reglas para que la investigación política sea sólida
Los datos políticos de Twitter miden la conversación en línea, no la opinión pública, y las reglas de abajo mantienen un estudio dentro de lo que los datos pueden mostrar.
- Los usuarios de X no son el electorado. En el estudio de Pew, los adultos de 50 años o más eran el 24% de los usuarios adultos de Estados Unidos y escribieron el 78% de sus tweets políticos. Toma los conteos como una medida de quién habla en X, nunca como una encuesta.
- Los bots y las cuentas coordinadas inflan los temas políticos. Fíltralos antes de contar e informa qué quitaste; la guía de detección de bots en Twitter enumera las señales.
- La consulta decide el resultado. Publica la consulta exacta, las ventanas, el endpoint y las fechas de recopilación, para que otras personas puedan reconstruir tu dataset.
- Estudia posts y cargos públicos, no votantes. Mide la conversación en conjunto y cita a los usuarios comunes con moderación. Inferir las opiniones políticas de una persona está fuera de los límites de la ética de la investigación, y el propio acuerdo para desarrolladores (se abre en una pestaña nueva) de X prohíbe perfilar a las personas por su afiliación política.
Para tener en cuenta
Los datos políticos sirven para entender la política, no para dirigir a los votantes. Limita una recopilación política a la investigación, el periodismo y el trabajo de rendición de cuentas: sin padrones de votantes, sin listas de segmentación y sin mensajes dirigidos a personas elegidas por lo que publican.
El etiquetado, la deduplicación y la división de un corpus para un modelo son iguales con los tweets políticos que con cualquier otro tipo, y la guía para crear un dataset de Twitter para machine learning los cubre. Medir el tono y la postura es el tema del análisis de sentimientos en Twitter.
#Empieza tu recopilación política con 100 solicitudes gratis
Para recopilar datos políticos de Twitter, empieza con Sorsa API: un feed de lista de seguimiento, timelines y búsqueda electoral con una sola clave API, desde $0.07 por 1,000 tweets, a 20 solicitudes por segundo en todos los planes. Las 100 solicitudes gratis devuelven unos 2,000 posts, sin tarjeta y sin vencimiento. Extrae una semana de tus cargos públicos o de tu contienda, revisa la consulta y después programa el resto. Los equipos universitarios también pueden solicitar el acceso de investigación académica de Sorsa API con un correo institucional.
#Preguntas frecuentes
¿Todavía se pueden obtener datos políticos de Twitter para investigar?
Sí. El acceso académico gratuito terminó en 2023, pero los posts políticos públicos se pueden seguir recopilando con una API. La API oficial de X cobra $0.005 por post y se detiene en 3 millones de posts al mes. Sorsa API lee los mismos posts públicos desde $0.07 por 1,000, con 100 solicitudes gratis para probar un estudio antes de presupuestarlo. También existen datasets publicados con IDs de tweets, aunque los posts eliminados ya no se devuelven desde ellos.
¿Cuál es la mejor API para datos políticos de Twitter?
Usa Sorsa API para los datos políticos de Twitter: lee timelines de políticos, feeds de Listas de X y búsquedas electorales desde $0.07 por 1,000 tweets, frente a $5.00 en la API oficial de X. Necesita una sola clave API y ninguna cuenta de desarrollador, funciona a 20 solicitudes por segundo en todos los planes, no tiene tope mensual de 3 millones y devuelve el perfil de cada autor sin cargo adicional. Es de solo lectura, así que nunca toca tu cuenta de X.
¿Se pueden obtener los tweets eliminados de los políticos?
Ninguna API devuelve un tweet después de que su autor lo elimina, incluida Sorsa API. Un post eliminado solo sobrevive donde alguien lo guardó antes: un archivo de prensa, una captura de un archivo web o tu propia recopilación. Para estudiar las eliminaciones, guarda cada post de tu lista de seguimiento cuando aparece por primera vez, luego vuelve a revisar los IDs guardados con POST /tweet-info-bulk de Sorsa API, 100 por solicitud, y registra los que dejan de aparecer.
¿Dónde puedo encontrar una lista de las cuentas de Twitter de los miembros del Congreso?
El proyecto de datos abiertos unitedstates/congress-legislators mantiene una en su archivo legislators-social-media.yaml. El 2 de noviembre de 2026 listaba 505 handles de X de miembros en funciones, 408 con IDs numéricos de usuario, e incluye solo cuentas oficiales, no de campaña. Resuelve los handles a IDs con GET /info-batch de Sorsa API, 100 por solicitud, y guarda los IDs, porque los handles cambian.
¿Pueden los datos de Twitter predecir los resultados electorales?
No por sí solos. Los usuarios de X no son una muestra de los votantes: en el estudio del Pew Research Center, los adultos de 50 años o más escribieron el 78% de los tweets políticos de los adultos de Estados Unidos aunque eran el 24% de los usuarios. Los conteos de posts y el sentimiento miden la conversación en línea, algo útil para estudiar agendas, campañas y reacciones, pero los pronósticos basados solo en ellos tienen un mal historial.
¿Pueden los investigadores de la UE obtener datos de X con la DSA?
Sí, a través del artículo 40 de la Ley de Servicios Digitales (DSA). Los investigadores acreditados pueden solicitar datos a las plataformas muy grandes, como X, por medio del Coordinador de Servicios Digitales de su país, para investigar riesgos sistémicos en la UE, entre ellos los riesgos para las elecciones y el debate cívico. El portal de acceso a datos de la UE recibe solicitudes desde el 29 de octubre de 2025. La aprobación toma tiempo, por lo que muchos equipos empiezan mientras tanto a recopilar posts públicos con una API.
#Cómo lo comprobamos
El 2 de noviembre de 2026 leímos la lista de precios de pago por uso de X, su acuerdo para desarrolladores del 27 de abril de 2026 y su aviso del 23 de octubre de 2026 sobre las expansiones de facturación; todos los precios y reglas de la API oficial de X que aparecen aquí salen de ellos. Ese mismo día descargamos el archivo de redes sociales de unitedstates/congress-legislators y contamos sus cuentas, y leímos el informe de 2022 del Pew Research Center y las preguntas frecuentes de la Comisión Europea sobre el acceso a datos de la DSA. Cada endpoint, parámetro y tamaño de página de Sorsa API se comprobó con nuestra referencia de la API en producción; las solicitudes y la respuesta se construyen a partir de ella con cuentas de demostración, y los costos son aritmética con las tarifas publicadas.
Fuentes
- X API pay-per-usage pricing (se abre en una pestaña nueva)
- X Developers: PPU expansions update (Oct 23, 2026) (se abre en una pestaña nueva)
- X Developer Agreement (April 27, 2026) (se abre en una pestaña nueva)
- unitedstates/congress-legislators: legislators-social-media.yaml (se abre en una pestaña nueva)
- Pew Research Center: Politics on Twitter (June 16, 2022) (se abre en una pestaña nueva)
- European Commission: FAQs on DSA data access for researchers (se abre en una pestaña nueva)
- Sorsa API docs: Lists and Communities (se abre en una pestaña nueva)
- Sorsa API reference (OpenAPI)