Rivalwin API — Google Ads Commercial
Descripción general
La API de Google Ads Commercial permite generar informes de publicidad comercial en Google Ads de forma programática. Utilizando la información del Google Ads, los informes analizan los anuncios de un competidor durante un período determinado, proporcionando datos de creatividades, formatos, períodos de actividad y análisis de IA.
Base URL: https://rivalwin.com/api/v1/google/companies/
Autenticación
Todas las peticiones requieren una API Key válida enviada en el header X-API-Key.
X-API-Key: tu_api_key_aqui
Rate Limiting
La API aplica dos tipos de limitación:
Rate limit por hora
Cada API Key tiene un límite de peticiones por hora configurado. Los headers de respuesta indican el estado:
X-RateLimit-Limit-Hour: 600
X-RateLimit-Remaining-Hour: 598
Si se excede el límite: 429 Too Many Requests con header Retry-After.
Cooldown entre informes
Existe un tiempo mínimo de espera entre la creación de informes consecutivos (por defecto 10 segundos, configurable por plan/empresa). Si intentas crear un informe antes de que transcurra este tiempo:
{
"error": "cooldown_active",
"message": "Please wait 7 seconds before creating another report.",
"cooldown_seconds": 10,
"retry_after": 7
}
Requisitos de la cuenta
- Su cuenta de Rivalwin debe estar activa.
- El plan contratado debe estar activo y no vencido (contrato o trial).
- El plan debe incluir acceso a la API.
Si alguna de estas condiciones no se cumple, recibirás un error 403 Forbidden con el motivo específico.
Recepción de resultados
Existen dos formas de recibir los datos de un informe completado:
Polling
Consulta el endpoint report_status periódicamente (cada 15-30 segundos) hasta que el estado sea DONE. Es el método más simple y no requiere configuración adicional.
Webhook
Configura una URL de webhook en el módulo Integraciones & API Keys del sistema. Cuando un informe pase al estado DONE, la API enviará automáticamente un POST a la URL configurada con el payload completo del informe (mismo contenido que devuelve report_status en estado DONE).
De esta forma no necesitas hacer polling: simplemente esperas a recibir la notificación en tu servidor.
Endpoints
1. Crear un nuevo informe de Google Ads (new_report)
Crea un informe de publicidad comercial de Google Ads de forma asíncrona. Devuelve inmediatamente un hash identificador.
POST /api/v1/google/companies/new_report
Headers
| Header | Tipo | Requerido | Descripción |
|---|---|---|---|
| X-API-Key | string | Sí | Tu API Key |
| Idempotency-Key | string | No | Clave de idempotencia para evitar informes duplicados |
| Content-Type | string | Sí | application/json |
Body (JSON)
| Parámetro | Tipo | Requerido | Descripción |
|---|---|---|---|
rival_ref | string | Sí | Referencia del rival |
date_from | string | Sí | Fecha inicio del período (YYYY-MM-DD) |
date_to | string | Sí | Fecha fin del período (YYYY-MM-DD) |
country | string | Sí | ISO-2 (ES, AR, EU, etc.) |
Ejemplo de petición
curl -X POST https://rivalwin.com/api/v1/google/companies/new_report \
-H "X-API-Key: tu_api_key" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: google-report-20260315" \
-d '{
"rival_ref": "rvl_0c526d93",
"date_from": "2026-03-01",
"date_to": "2026-03-31",
"country": "AR"
}'
Respuesta exitosa (202 Accepted)
{
"hash": "d63f7c339b13a4e5f6c7d8e9f0a1b2c3",
"status": "PENDING",
"created_at": "2026-03-15 16:00:00"
}
Validaciones y restricciones
| Regla | Detalle |
|---|---|
| Rango máximo de fechas | 60 días |
| Fecha fin máxima | Ayer (no se permite el día actual ni futuro) |
| Fecha inicio mínima | Hasta 1 año atrás |
| Formato de fecha | YYYY-MM-DD estricto |
| País | ISO-2 (ES, AR, EU, etc.) |
| Créditos | Se descuentan al crear el informe |
Idempotencia
Si envías el header Idempotency-Key con un valor previamente usado, la API devuelve el informe existente sin crear uno nuevo ni descontar créditos adicionales.
2. Consultar estado del informe (report_status)
Consulta el estado de un informe y obtiene los datos del reporte cuando está completo.
POST /api/v1/google/companies/report_status
Headers requeridos
| Header | Tipo | Requerido | Descripción |
|---|---|---|---|
| X-API-Key | string | Sí | Tu API Key |
| Content-Type | string | Sí | application/json |
Body (JSON)
| Parámetro | Tipo | Requerido | Descripción |
|---|---|---|---|
hash | string | Sí | Hash del informe (obtenido de new_report) |
Ejemplo de petición
curl -X POST https://rivalwin.com/api/v1/google/companies/report_status \
-H "X-API-Key: tu_api_key" \
-H "Content-Type: application/json" \
-d '{"hash": "...."}'
Respuesta según estado
PENDING — El informe está en cola:
{
"hash": "...",
"status": "PENDING",
"created_at": "2026-03-15 16:00:00",
"message": "The report is queued and will start processing shortly."
}
PROCESSING — El informe se está generando:
{
"hash": "...",
"status": "PROCESSING",
"created_at": "2026-03-15 16:00:00",
"started_at": "2026-03-15 16:00:05",
"message": "The report is being generated. Please check back in a few moments."
}
DONE — El informe está completo con todos los datos:
{
"hash": "...",
"status": "DONE",
"created_at": "2026-03-15 16:00:00",
"started_at": "2026-03-15 16:00:05",
"completed_at": "2026-03-15 16:02:15",
"report": {
"report_id": 6198,
"platform": "Google",
"rival": {
"ref": "rvl_0c526d93",
"name": "Empresa Competidora S.A.",
"logo": "https://..../empresa.png",
"web": "https://empresa.com",
"description": "Competidor en el sector financiero",
"google_id": "AR123456789"
},
"sector": "Finanzas",
"country": "AR",
"campaign_start": "2026-03-01",
"campaign_end": "2026-03-31",
"inform_created": "2026-03-15 16:00:00",
"kpis": {
"ads_total": 7,
"started_in_period": 3,
"active_in_period": 7,
"active_now": 2
},
"insights": {
"gpt_analysis": "<p>Análisis detallado de la estrategia en Google Ads generado por IA...</p>"
},
"ads": [
{
"creative_id": "CR123456789",
"advertiser": "Empresa Competidora S.A.",
"first_shown": "2026-02-15",
"last_shown": "2026-03-28",
"total_days_shown": 41,
"format": "IMAGE",
"transparency_url": "https://....",
"creatives": [
"https://..../image1.jpg",
"https://..../image2.jpg"
]
}
],
"pdf_url": "https://..../report_6198.pdf"
}
}
ERROR — Error durante la generación:
{
"hash": "...",
"status": "ERROR",
"created_at": "2026-03-15 16:00:00",
"completed_at": "2026-03-15 16:01:00",
"error_message": "Report failed during processing."
}
Estructura completa del reporte
Campos principales (report)
| Campo | Tipo | Descripción |
|---|---|---|
report_id | int | ID interno del informe |
platform | string | Plataforma analizada (Google) |
rival | object | Datos del competidor analizado |
sector | string | Sector o industria del competidor |
country | string | País filtrado (o anywhere si se usó ALL_COUNTRIES) |
campaign_start | string | Fecha inicio del período analizado |
campaign_end | string | Fecha fin del período analizado |
inform_created | string | Fecha de creación del informe |
kpis | object | Indicadores clave del período |
insights | object | Análisis generado por IA |
ads | array | Lista de anuncios encontrados y filtrados por período |
pdf_url | string | URL del PDF del informe (si está disponible) |
Datos del rival (rival)
| Campo | Tipo | Descripción |
|---|---|---|
ref | string | Referencia del rival |
name | string | Nombre de la empresa |
logo | string | URL del logo (puede ser null) |
web | string | Sitio web (puede ser null) |
description | string | Descripción del competidor |
google_id | string | ID del anunciante en Google Ads Transparency Center |
KPIs (kpis)
| Campo | Tipo | Descripción |
|---|---|---|
ads_total | integer | Total de anuncios activos durante el período analizado |
started_in_period | integer | Anuncios que comenzaron a mostrarse dentro del período |
active_in_period | integer | Anuncios que estuvieron activos en algún momento del período |
active_now | integer | Anuncios que están activos actualmente (al momento de generar el informe) |
Anuncios (ads[])
Cada anuncio contiene la siguiente información:
| Campo | Tipo | Descripción |
|---|---|---|
creative_id | string | ID único de la creatividad en Google Ads Transparency Center |
advertiser | string | Nombre del anunciante |
first_shown | string | Fecha en que se mostró por primera vez (YYYY-MM-DD) |
last_shown | string | Última fecha en que se vio activo (YYYY-MM-DD) |
total_days_shown | integer | Total de días que estuvo visible |
format | string | Formato del anuncio (IMAGE, VIDEO, TEXT, etc.) |
transparency_url | string | URL directa al anuncio en Google Ads Transparency Center |
creatives | array | Lista de URLs de las imágenes/creatividades extraídas (puede ser null) |
Sobre las creatividades (creatives)
Las creatividades son URLs de imágenes extraídas de las variantes del anuncio. Un anuncio puede tener múltiples variantes (diferentes tamaños o versiones), y cada una puede contener una imagen.
"creatives": [
"https://.../creative_variant_1.jpg",
"https://.../creative_variant_2.jpg"
]
Si no se pudieron extraer creatividades del anuncio, el campo será null.
Sobre el filtrado de anuncios por período
Los anuncios devueltos están filtrados para coincidir con el período solicitado. Un anuncio se incluye si existe solapamiento entre su rango de actividad (first_shown → last_shown) y el período del informe (date_from → date_to).
Ejemplo:
- Período del informe:
2026-03-01a2026-03-31 - Anuncio con
first_shown: 2026-02-15ylast_shown: 2026-03-10→ Incluido (se solapa) - Anuncio con
first_shown: 2026-01-01ylast_shown: 2026-02-28→ Excluido (no se solapa)
Insights de IA (insights)
| Campo | Tipo | Descripción |
|---|---|---|
gpt_analysis | string | Análisis HTML generado por IA sobre la estrategia en Google Ads |
El análisis incluye observaciones sobre los formatos de anuncios utilizados, frecuencia de publicación, estrategia creativa y recomendaciones. Viene en formato HTML con etiquetas como <p>, <ul>, <li>, <strong>, etc.
Ejemplos de código
PHP
<?php
$apiKey = "tu_api_key";
$baseUrl = "https://rivalwin.com/api/v1/google/companies";
$rivalRef = "rvl_0c526d93";
// 1. Crear informe
$report = apiCall("$baseUrl/new_report", [
'rival_ref' => $rivalRef,
'date_from' => '2026-03-01',
'date_to' => '2026-03-31',
'country' => 'AR', // o 'ALL_COUNTRIES' para todos los países
], $apiKey);
$hash = $report['hash'];
echo "Informe creado: $hash\n";
// 2. Polling hasta completar
do {
sleep(20);
$status = apiCall("$baseUrl/report_status", ['hash' => $hash], $apiKey);
echo "Estado: " . $status['status'] . "\n";
} while (in_array($status['status'], ['PENDING', 'PROCESSING']));
// 3. Procesar resultado
if ($status['status'] === 'DONE') {
$data = $status['report'];
echo "\n=== INFORME GOOGLE ADS ===\n";
echo "Rival: " . $data['rival']['name'] . "\n";
echo "Google ID: " . $data['rival']['google_id'] . "\n";
echo "Período: " . $data['campaign_start'] . " → " . $data['campaign_end'] . "\n";
echo "\nKPIs:\n";
echo " Total anuncios: " . $data['kpis']['ads_total'] . "\n";
echo " Iniciados en período: " . $data['kpis']['started_in_period'] . "\n";
echo " Activos en período: " . $data['kpis']['active_in_period'] . "\n";
echo " Activos ahora: " . $data['kpis']['active_now'] . "\n";
echo "\nAnuncios:\n";
foreach ($data['ads'] as $i => $ad) {
echo " " . ($i + 1) . ". Creative: {$ad['creative_id']}\n";
echo " Formato: {$ad['format']}\n";
echo " Período: {$ad['first_shown']} → {$ad['last_shown']} ({$ad['total_days_shown']} días)\n";
echo " URL: {$ad['transparency_url']}\n";
if (!empty($ad['creatives'])) {
echo " Creatividades: " . count($ad['creatives']) . " imagen(es)\n";
foreach ($ad['creatives'] as $img) {
echo " - $img\n";
}
}
echo "\n";
}
}
function apiCall(string $url, array $body, string $apiKey): array {
$ch = curl_init($url);
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => json_encode($body),
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
'Content-Type: application/json',
'X-API-Key: ' . $apiKey,
],
]);
$response = curl_exec($ch);
curl_close($ch);
return json_decode($response, true);
}
Python
import requests
import time
api_key = "tu_api_key"
base_url = "https://rivalwin.com/api/v1/google/companies"
headers = {
"Content-Type": "application/json",
"X-API-Key": api_key,
}
rival_ref = "rvl_0c526d93"
# 1. Crear informe (con ALL_COUNTRIES para buscar globalmente)
report = requests.post(f"{base_url}/new_report", json={
"rival_ref": rival_ref,
"date_from": "2026-03-01",
"date_to": "2026-03-31",
"country": "ALL_COUNTRIES",
}, headers=headers).json()
hash_id = report["hash"]
print(f"Informe creado: {hash_id}")
# 2. Polling
while True:
time.sleep(20)
result = requests.post(f"{base_url}/report_status",
json={"hash": hash_id}, headers=headers).json()
print(f"Estado: {result['status']}")
if result["status"] not in ["PENDING", "PROCESSING"]:
break
# 3. Resultados
if result["status"] == "DONE":
data = result["report"]
print(f"\nRival: {data['rival']['name']}")
print(f"Google ID: {data['rival']['google_id']}")
print(f"Total anuncios: {data['kpis']['ads_total']}")
print(f"Activos ahora: {data['kpis']['active_now']}")
for ad in data["ads"]:
print(f"\n Creative: {ad['creative_id']}")
print(f" Formato: {ad['format']}")
print(f" Visible: {ad['first_shown']} → {ad['last_shown']} ({ad['total_days_shown']} días)")
if ad.get("creatives"):
for img in ad["creatives"]:
print(f" Imagen: {img}")
JavaScript (Node.js)
const API_KEY = "tu_api_key";
const BASE_URL = "https://rivalwin.com/api/v1/google/companies";
async function apiCall(endpoint, body = {}) {
const res = await fetch(`${BASE_URL}/${endpoint}`, {
method: "POST",
headers: {
"Content-Type": "application/json",
"X-API-Key": API_KEY,
},
body: JSON.stringify(body),
});
return res.json();
}
async function main() {
const rivalRef = "rvl_0c526d93";
// 1. Crear informe
const report = await apiCall("new_report", {
rival_ref: rivalRef,
date_from: "2026-03-01",
date_to: "2026-03-31",
country: "AR",
});
console.log(`Informe creado: ${report.hash}`);
// 2. Polling
let result;
do {
await new Promise(r => setTimeout(r, 20000));
result = await apiCall("report_status", { hash: report.hash });
console.log(`Estado: ${result.status}`);
} while (["PENDING", "PROCESSING"].includes(result.status));
// 3. Resultados
if (result.status === "DONE") {
const data = result.report;
console.log(`\nRival: ${data.rival.name}`);
console.log(`Anuncios: ${data.kpis.ads_total}`);
data.ads.forEach(ad => {
console.log(` ${ad.creative_id} | ${ad.format} | ${ad.first_shown} → ${ad.last_shown}`);
});
}
}
main().catch(console.error);
Códigos de error
| Código HTTP | Error | Descripción |
|---|---|---|
| 400 | missing_parameters | Faltan parámetros requeridos en el body |
| 400 | invalid_date_from | Formato de date_from inválido (debe ser YYYY-MM-DD) |
| 400 | invalid_date_to | Formato de date_to inválido (debe ser YYYY-MM-DD) |
| 400 | invalid_date_range | Rango de fechas inválido (futuro, invertido o > 60 días) |
| 400 | invalid_country | Código de país inválido (debe ser 2 letras ISO o ALL_COUNTRIES) |
| 400 | rival_no_google_id | El rival no tiene un Google Ads Transparency ID configurado |
| 401 | missing_api_key | No se envió el header X-API-Key |
| 401 | invalid_api_key | La API Key no es válida o está revocada |
| 402 | insufficient_credits | Créditos insuficientes para generar el informe |
| 403 | account_inactive | La cuenta de la empresa está desactivada |
| 403 | plan_inactive | El plan contratado está desactivado |
| 403 | contract_expired | El contrato ha expirado |
| 403 | trial_expired | El período de prueba ha expirado |
| 403 | api_not_in_plan | El plan no incluye acceso a la API |
| 404 | rival_not_found | El rival_ref no existe o está inactivo |
| 404 | rival_data_not_found | Datos del rival no encontrados en el sistema |
| 404 | job_not_found | No se encontró un informe con el hash proporcionado |
| 429 | rate_limit_exceeded | Se excedió el límite de peticiones por hora |
| 429 | cooldown_active | Debe esperar antes de crear otro informe |
| 500 | internal_error | Error interno del servidor |
Notas importantes
- Los informes se generan de forma asíncrona. La creación devuelve un
hashinmediatamente y el informe se procesa en segundo plano. - El tiempo de generación típico es de 1 a 4 minutos, dependiendo del volumen de anuncios y la generación del análisis IA + PDF.
- Google Ads no proporciona datos de inversión, impresiones ni demografía. Los KPIs se centran en la cantidad y actividad temporal de los anuncios.
- El
pdf_urlcontiene el informe visual en formato PDF listo para descarga. - Cada informe consume créditos según el sistema.
- El
gpt_analysisviene en formato HTML y puede contener etiquetas<p>,<ul>,<li>,<strong>, etc.