El Gestor de anuncios sirve para montar una campaña; para llevar diez, sacar informes cada mañana o enterarte de un rechazo sin estar mirando, necesitas la API de ChatGPT Ads (OpenAI llama a la plataforma, en español, «ChatGPT Anuncios»).
Casi todas las trampas de esa API las medimos al montar nuestra campaña: aquí van, para que no las pagues tú.
Qué cubre
Campañas, grupos, anuncios, imágenes, audiencias propias (que hoy no se admiten en campañas para el Espacio Económico Europeo ni Suiza), conversiones, informes y operaciones masivas, en la versión v1. Ojo: para enviar conversiones se usa otra clave (lección 4).
Autenticación: una clave por cuenta
- La clave se crea en el Gestor, en Settings → API Keys, y viaja en
la cabecera
Authorization: Bearer. - No es la clave de conversiones, que se crea en Conversiones, tras el icono de la llave: son fáciles de confundir.
- Cada clave pertenece a una cuenta. La guía para socios pide usar la clave de la cuenta del cliente en cada petición y guardarla en un gestor de secretos del servidor. Nunca en el navegador.
- Si envías conversiones en nombre de clientes, todas las peticiones
llevan el mismo identificador
integration_source.
Varias cuentas: no hay MCC
Si vienes de Google Ads, no busques el MCC: no existe. Cada anunciante tiene su cuenta, que una agencia no puede crear por su cliente (la crea el cliente e invita a la agencia); un usuario puede entrar en varias y cambiar de una a otra, pero sin vista conjunta. Los roles van por cuenta: administrador, miembro y lector.
Por API, llevar diez cuentas es guardar diez claves, y el «MCC» pasa a ser una herramienta tuya que las junte. En Ninja Scripts estamos construyendo justo eso en nuestro panel.
Límites
- 600 peticiones por minuto por endpoint y 1.200 en total.
- Operaciones masivas: 10 cada 10 segundos por cuenta.
- Cabecera opcional
Idempotency-Key, para que un reintento no duplique lo que ya se creó.
Las trampas de la API
| Trampa | Qué pasa | Qué hacer |
|---|---|---|
Actualizar con PATCH o PUT |
Devuelven 405 | Actualiza con POST |
| Borrar | No hay DELETE |
Archiva lo que retires (una audiencia archivada no vuelve) |
| Leer justo después de escribir | Consistencia eventual: un anuncio archivado se leía «pausado» al instante y «archivado» a los 10 segundos | Espera y relee antes de darlo por hecho |
| Listar | No devuelven el padre: el listado de grupos no dice de qué campaña es cada uno | Filtra por el padre en la URL |
| Parámetros que no existen | Se ignoran sin error: nuestro informe con level y start_date habría traído el total de la cuenta, sin desglose por anuncio |
Prueba cada parámetro con un valor inválido: si no da 400, no existe |
| Simular | La API de gestión no tiene modo de simulación ni transacciones; la de conversiones sí trae validate_only, que valida sin guardar |
Simula tú los cambios; prueba las conversiones con validate_only |
| Importes | Pujas y presupuestos van en micros (1 = 1.000.000; un CPM de 60 $ se envía como 0,06 $ por impresión = 60.000 micros); el gasto del informe llega en la moneda de la cuenta | Convierte en un solo sitio del código |
| Subir imágenes | Sin tipo MIME da 400 aunque el PNG esté bien; mínimo 640×640 | Declara el tipo del archivo |
| Pistas de contexto | La lista que envías reemplaza a la anterior | Envía siempre la lista completa |
| Editar la creatividad | Crea una versión nueva y otra revisión | Tócala solo cuando quieras cambiarla |
| Deduplicar píxel y servidor | El identificador del evento es event_id en el píxel e id en la API de conversiones |
Mismo valor en ambos, con el mismo píxel y el mismo nombre de evento |
| Un anuncio que no sale | Activar no basta: lo bloquean una revisión de cuenta pendiente, un tope de gasto agotado o problemas de campaña | Pide include[]=serving_issues; a nosotros nos dijo «revisión de marca de la cuenta en curso» |
Dos matices: una lista de serving_issues vacía no promete impresiones,
y bid_too_low en un grupo orienta, no bloquea. Y un 200 solo dice que
la API no ha protestado, no que haya hecho lo que querías.
Un informe por anuncio, bien pedido
curl -G "https://api.ads.openai.com/v1/ad_account/insights" \
-H "Authorization: Bearer $OPENAI_ADS_API_KEY" \
--data-urlencode "aggregation_level=ad" \
--data-urlencode "time_granularity=daily" \
--data-urlencode 'time_ranges[]={"type":"date_range","since":"2026-09-01","until":"2026-09-15","timezone":"Europe/Madrid"}'
aggregation_level=ad pide una fila por anuncio;
time_granularity=daily, una por día, y time_ranges[], el periodo con
su zona horaria. Son los nombres reales: con un valor inválido, los tres
dan 400. -G pasa los datos a la URL y --data-urlencode los codifica
(el JSON lo necesita). La clave sale de una variable de entorno, nunca
del comando.
Antes de fiarte, comprueba que las filas traen anuncio y día (un total sin ellos delata un parámetro ignorado); y los últimos días aún pueden cambiar, porque el gasto y las conversiones llegan tarde (lección 5).
💡 Truco ninja: antes de usar un parámetro nuevo, llámalo con un valor absurdo. Si la API responde 400, existe y lo valida; si responde 200, no existe y lo está ignorando.
⚠️ Trampa: si tu herramienta comprueba las URL de los anuncios, esas visitas pueden entrar en tu analítica como personas llegadas del anuncio. Nos pasó: ahora las filtramos exigiendo que cada visita la confirme un navegador.
Buenas prácticas
- Todo nace en pausa: que tu código active solo tras revisar (la vista previa caduca a las 24 horas). Un anuncio activo necesita campaña y grupo activos.
- La clave, cifrada en el servidor: una por cuenta, en un gestor de secretos.
- Registro de cambios: qué, cuándo, antes, después y por qué. Sin él no sabrás qué causó qué (lección 7).
Qué debes recordar
- Una clave por cuenta, en el servidor, y otra distinta para enviar conversiones.
- No hay MCC: el «MCC» es tu herramienta, con la clave de cada cliente.
- Límites: 600 peticiones por minuto por endpoint y 1.200 en total; masivas, 10 cada 10 segundos.
- POST para actualizar, archivar en vez de borrar y releer tras escribir.
- Un parámetro que no da 400 con un valor inválido no existe.
- Micros al enviar pujas y presupuestos; moneda de la cuenta al leer el gasto.