Skip to main content

Rivalwin API — TikTok Ads Commercial

Descripción general

La API de TikTok Ads Commercial permite generar informes de publicidad comercial de forma programática. Utilizando la información del TikTok, los informes analizan los anuncios de un competidor durante un período determinado, proporcionando datos de creatividades (videos e imágenes), alcance estimado, períodos de actividad y análisis de IA.

Base URL: https://rivalwin.com/api/v1/tiktok/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 TikTok Ads

Crea un informe de publicidad comercial de TikTok Ads de forma asíncrona. Devuelve inmediatamente un hash identificador.

POST /api/v1/tiktok/companies/new_report

Headers

HeaderTipoRequeridoDescripción
X-API-KeystringTu API Key
Idempotency-KeystringNoClave de idempotencia para evitar informes duplicados
Content-Typestringapplication/json

Body (JSON)

ParámetroTipoRequeridoDescripción
rival_refstringReferencia del rival
date_fromstringFecha inicio del período (YYYY-MM-DD)
date_tostringFecha fin del período (YYYY-MM-DD)
countrystringCódigo de país ISO de 2 letras (ej: AR, US)

Ejemplo de petición

curl -X POST https://rivalwin.com/api/v1/tiktok/companies/new_report \
-H "X-API-Key: tu_api_key" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: tiktok-report-20260315" \
-d '{
"rival_ref": "rvl_0c526d93",
"date_from": "2026-03-01",
"date_to": "2026-03-31",
"country": "ES"
}'

Respuesta exitosa (202 Accepted)

{
"hash": "...",
"status": "PENDING",
"created_at": "2026-03-15 16:00:00"
}

Validaciones y restricciones

ReglaDetalle
Rango máximo de fechas60 días
Fecha fin máximaAyer (no se permite el día actual ni futuro)
Fecha inicio mínimaHasta 1 año atrás
Formato de fechaYYYY-MM-DD estricto
PaísCódigo ISO de 2 letras
CréditosSe 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

Consulta el estado de un informe y obtiene los datos del reporte cuando está completo.

POST /api/v1/tiktok/companies/report_status

Headers requeridos

HeaderTipoRequeridoDescripción
X-API-KeystringTu API Key
Content-Typestringapplication/json

Body (JSON)

ParámetroTipoRequeridoDescripción
hashstringHash del informe (obtenido de new_report)

Ejemplo de petición

curl -X POST https://rivalwin.com/api/v1/tiktok/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": "TikTok",
"rival": {
"ref": "rvl_0c526d93",
"name": "Empresa Competidora S.L.",
"logo": "https://rivalwin.com/uploads/logos/empresa.png",
"web": "https://empresa.com",
"description": "Competidor en el sector retail",
"tiktok_id": "7123456789012345678"
},
"sector": "Retail",
"country": "ES",
"campaign_start": "2026-03-01",
"campaign_end": "2026-03-31",
"inform_created": "2026-03-15 16:00:00",
"kpis": {
"ads_total": 23,
"with_video": 18,
"with_image_only": 5
},
"insights": {
"gpt_analysis": "Análisis detallado de la estrategia en TikTok Ads."
},
"ads": [
{
"ad_id": "12345678901234",
"first_shown": "2026-03-01",
"last_shown": "2026-03-28",
"status": "active",
"advertiser": {
"business_id": "7123456789012345678",
"business_name": "Empresa Competidora S.L.",
"paid_for_by": "Empresa Competidora S.L."
},
"video_url": "https://v16-webapp-prime.tiktok.com/video/...",
"thumbnail_url": "https://p16-sign.tiktokcdn-us.com/...",
"image_urls": [],
"reach": "10K-50K",
"estimated_audience": {
"label": "10K-50K",
"min": 10000,
"max": 50000
}
}
]
}
}

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)

CampoTipoDescripción
report_idintID interno del informe
platformstringPlataforma analizada (TikTok)
rivalobjectDatos del competidor analizado
sectorstringSector o industria del competidor
countrystringPaís filtrado
campaign_startstringFecha inicio del período analizado
campaign_endstringFecha fin del período analizado
inform_createdstringFecha de creación del informe
kpisobjectIndicadores clave del período
insightsobjectAnálisis generado por IA
adsarrayLista de anuncios encontrados

Datos del rival (rival)

CampoTipoDescripción
refstringReferencia del rival
namestringNombre de la empresa
logostringURL del logo (puede ser null)
webstringSitio web (puede ser null)
descriptionstringDescripción del competidor

KPIs (kpis)

CampoTipoDescripción
ads_totalintegerTotal de anuncios encontrados en el período analizado
with_videointegerAnuncios que contienen creatividades de video
with_image_onlyintegerAnuncios que solo contienen imágenes (sin video)

Anuncios (ads[])

Cada anuncio contiene la siguiente información:

CampoTipoDescripción
ad_idstringID único del anuncio en TikTok Ad Library
first_shownstringFecha en que se mostró por primera vez (YYYY-MM-DD)
last_shownstringÚltima fecha en que se vio activo (YYYY-MM-DD)
statusstringEstado del anuncio (active, inactive, etc.)
advertiserobjectDatos del anunciante
video_urlstringURL del video del anuncio (puede ser null)
thumbnail_urlstringURL de la imagen de portada / thumbnail
image_urlsarrayURLs de imágenes del anuncio
reachstringAlcance estimado en formato legible (ej: "10K-50K")
estimated_audienceobjectDesglose numérico del alcance estimado

Datos del anunciante (advertiser)

CampoTipoDescripción
business_namestringNombre comercial del anunciante
paid_for_bystringEntidad que paga por el anuncio

Audiencia estimada (estimated_audience)

CampoTipoDescripción
labelstringRango en formato legible (ej: "10K-50K")
minintegerLímite inferior estimado (puede ser null)
maxintegerLímite superior estimado (puede ser null)

Ejemplos de código

PHP

<?php
$apiKey = "tu_api_key";
$baseUrl = "https://rivalwin.com/api/v1/tiktok/companies";

// 1. Crear informe
$report = apiCall("$baseUrl/new_report", [
'rival_ref' => 'rvl_0c526d93',
'date_from' => '2026-03-01',
'date_to' => '2026-03-31',
'country' => 'ES',
], $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 TIKTOK ADS ===\n";
echo "Rival: " . $data['rival']['name'] . "\n";
echo "TikTok ID: " . $data['rival']['tiktok_id'] . "\n";
echo "Período: " . $data['campaign_start'] . " → " . $data['campaign_end'] . "\n";
echo "\nKPIs:\n";
echo " Total anuncios: " . $data['kpis']['ads_total'] . "\n";
echo " Con video: " . $data['kpis']['with_video'] . "\n";
echo " Solo imagen: " . $data['kpis']['with_image_only'] . "\n";

echo "\nAnuncios:\n";
foreach ($data['ads'] as $i => $ad) {
echo " " . ($i + 1) . ". Ad ID: {$ad['ad_id']}\n";
echo " Anunciante: {$ad['advertiser']['business_name']}\n";
echo " Período: {$ad['first_shown']}{$ad['last_shown']}\n";
echo " Alcance: {$ad['reach']}\n";

if (!empty($ad['video_url'])) {
echo " Video: {$ad['video_url']}\n";
}
if (!empty($ad['thumbnail_url'])) {
echo " Thumbnail: {$ad['thumbnail_url']}\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/tiktok/companies"
headers = {
"Content-Type": "application/json",
"X-API-Key": api_key,
}

# 1. Crear informe
report = requests.post(f"{base_url}/new_report", json={
"rival_ref": "rvl_0c526d93",
"date_from": "2026-03-01",
"date_to": "2026-03-31",
"country": "ES",
}, 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"TikTok ID: {data['rival']['tiktok_id']}")
print(f"Total anuncios: {data['kpis']['ads_total']}")
print(f"Con video: {data['kpis']['with_video']}")

for ad in data["ads"]:
print(f"\n Ad: {ad['ad_id']}")
print(f" Alcance: {ad['reach']}")
print(f" Visible: {ad['first_shown']}{ad['last_shown']}")
if ad.get("video_url"):
print(f" Video: {ad['video_url']}")

JavaScript (Node.js)

const API_KEY = "tu_api_key";
const BASE_URL = "https://rivalwin.com/api/v1/tiktok/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() {
// 1. Crear informe
const report = await apiCall("new_report", {
rival_ref: "rvl_0c526d93",
date_from: "2026-03-01",
date_to: "2026-03-31",
country: "ES",
});
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(`TikTok ID: ${data.rival.tiktok_id}`);
console.log(`Anuncios: ${data.kpis.ads_total}`);
data.ads.forEach(ad => {
console.log(` ${ad.ad_id} | ${ad.reach} | ${ad.first_shown}${ad.last_shown}`);
});
}
}

main().catch(console.error);

Códigos de error

Código HTTPErrorDescripción
400missing_parametersFaltan parámetros requeridos en el body
400invalid_date_fromFormato de date_from inválido (debe ser YYYY-MM-DD)
400invalid_date_toFormato de date_to inválido (debe ser YYYY-MM-DD)
400invalid_date_rangeRango de fechas inválido (futuro, invertido o > 60 días)
400invalid_countryCódigo de país inválido (debe ser 2 letras ISO o ALL_COUNTRIES)
400rival_no_tiktok_idEl rival no tiene un TikTok Business ID configurado
401missing_api_keyNo se envió el header X-API-Key
401invalid_api_keyLa API Key no es válida o está revocada
402insufficient_creditsCréditos insuficientes para generar el informe
403account_inactiveLa cuenta de la empresa está desactivada
403plan_inactiveEl plan contratado está desactivado
403contract_expiredEl contrato ha expirado
403trial_expiredEl período de prueba ha expirado
403api_not_in_planEl plan no incluye acceso a la API
404rival_not_foundEl rival_ref no existe o está inactivo
404rival_data_not_foundDatos del rival no encontrados en el sistema
404job_not_foundNo se encontró un informe con el hash proporcionado
429rate_limit_exceededSe excedió el límite de peticiones por hora
429cooldown_activeDebe esperar antes de crear otro informe
500internal_errorError interno del servidor

Notas importantes

  • Los informes se generan de forma asíncrona. La creación devuelve un hash inmediatamente y el informe se procesa en segundo plano.
  • El tiempo de generación típico es de 1 a 5 minutos, dependiendo del volumen de anuncios y la generación del análisis IA.
  • La mayoría de los anuncios de TikTok son videos. El campo video_url contiene la URL directa al video cuando está disponible.
  • El campo ads_data_url contiene una URL firmada (válida por 1 hora) que permite descargar el JSON crudo completo de anuncios.
  • Cada informe consume créditos según el sistema.