API de servidor
Última actualización: 13 nov 2026
Confirma una conversión desde tu backend con una petición HTTP autenticada con la clave de servidor del proyecto. No necesitas ningún SDK de servidor.
La evidencia del navegador puede perderse: una pestaña se cierra durante el pago, una extensión bloquea la solicitud o falla la red. Confirmar la conversión desde tu backend cubre ese hueco. La evidencia del navegador y la del servidor cuentan como una sola conversión porque comparten el mismo identificador estable.
Envía la conversión desde tu servidor con una petición HTTP y la clave de servidor del proyecto. No hay ningún SDK de servidor que instalar. Si instalas con una etiqueta script o con npm, Instalación y claves, en tu proyecto, te da la petición con las conversiones de tu recorrido ya puestas.
Endpoint
https://api.tracelog.io/v1/server/events
Envía un POST con Content-Type: application/json y la clave de servidor
del proyecto como bearer token en Authorization:
Authorization: Bearer tl_sk_xxxxxxxxxxxxxxxxxxxxxxxxxxLa clave es secreta. No está limitada a las direcciones de tu web, permite escribir eventos a cualquiera que la posea y nunca debe llegar al bundle del navegador. Rótala desde la página Instalación y claves del proyecto; el valor solo se muestra al crearla o rotarla.
El payload
{
"v": 1,
"events": [
{
"eventId": "019b9ae7-2c00-7000-8000-000000000001",
"sessionId": "019b9ae7-2c00-7000-8000-000000000002",
"kind": "conversion",
"name": "purchase",
"occurredAt": "2026-01-08T00:00:00.000Z",
"identifier": "wc-1042",
"value": 129.5,
"currency": "EUR"
}
]
}| Campo | Tipo | Descripción |
|---|---|---|
v | 1 | Versión del payload. Una versión desconocida se rechaza como unknown_version; nunca se interpreta por aproximación. |
eventId | UUID v7 | Clave de idempotencia. Reenviar el mismo valor no duplica el recuento, por lo que es seguro reintentar tras un timeout. |
sessionId | UUID v7 | Créalo y guárdalo con la conversión. El código de captura no expone la sesión del navegador, y la confirmación del servidor no la necesita. |
kind | string | conversion, step, session_start o error. |
name | string | Nombre en el recorrido de conversión: minúsculas, empezar por una letra y continuar con letras, números o guiones bajos, hasta 64 caracteres. |
occurredAt | ISO 8601 | Momento del evento en UTC y con milisegundos. TraceLog asigna el evento a esta hora, no a la de llegada. |
identifier | string | Obligatorio para conversiones, entre 1 y 256 caracteres. Tu identificador estable. |
value | number | Opcional, igual o mayor que cero. |
currency | string | Opcional, código ISO 4217 de tres letras mayúsculas. |
items | array | Opcional, en una conversión o un paso: hasta 100, cada uno con un ID, un nombre, una categoría opcional, una cantidad desde 1 y un precio unitario opcional. |
scheduledFor | string | Opcional, en una conversión: para qué día es, AAAA-MM-DD. |
recurring | boolean | Opcional, en una conversión: si es periódica. |
first | boolean | Opcional, en una conversión: true si tus registros no tienen ninguna conversión anterior de este tipo hecha por la misma persona, false si la tienen; omítelo si no lo sabes. |
mode | string | Opcional. verification marca tráfico de verificación, que no cuenta en las métricas ni en el límite de sesiones. Úsalo cuando el modo de prueba de tu sistema haya generado el pedido. |
context | object | Opcional. Objeto serializable como JSON, hasta 8 KB. |
Una conversión necesita seis campos: eventId, sessionId, kind, name,
occurredAt e identifier. Cada lote admite como máximo 50 eventos y cada
solicitud, 256 KB. Se rechaza
un evento situado más de cinco minutos en el futuro. Si tiene más de siete
días, se acepta pero queda marcado como tardío.
Si items, scheduledFor, recurring o first están mal formados, se
descartan y el evento se conserva. Cuando tu servidor y el navegador envían
artículos de una misma conversión, TraceLog se queda con los de tu servidor si
su occurredAt cae en el día en que se hizo la conversión, según la zona
horaria del proyecto. Un artículo cuyo ID es (other) se cuenta en «Otros»,
junto con los que pasan de los 500 de cada día.
Respuesta
{ "accepted": 1, "rejected": [] }accepted cuenta los eventos que esa solicitud ha guardado. Un solo evento no
válido rechaza el lote completo: no se guarda nada, y rejected enumera cada
eventId que haya podido leerse con el motivo del lote (unknown_version,
invalid_schema o future_time). Un eventId o un sessionId que no sea un
UUID v7 es invalid_schema.
Las cifras de un día admiten eventos tardíos durante 30 días. Un evento de hace
más de 30 días es expired: se rechaza él solo y el resto del lote se guarda.
Una solicitud de más de 256 KB o de más de 50 eventos se rechaza entera con un
HTTP 413 y sin recibo: eso es too_large. Si una misma clave envía demasiadas
solicitudes, recibe un HTTP 429 con una cabecera Retry-After en segundos.
Ejemplos
Los ejemplos leen dos variables: TRACELOG_API, con el valor https://api.tracelog.io, y
TRACELOG_SERVER_KEY, la clave de servidor del proyecto.
curl -X POST "$TRACELOG_API/v1/server/events" \
-H "Authorization: Bearer $TRACELOG_SERVER_KEY" \
-H "Content-Type: application/json" \
-d '{
"v": 1,
"events": [{
"eventId": "019b9ae7-2c00-7000-8000-000000000001",
"sessionId": "019b9ae7-2c00-7000-8000-000000000002",
"kind": "conversion",
"name": "purchase",
"occurredAt": "2026-01-08T00:00:00.000Z",
"identifier": "1042",
"value": 129.5,
"currency": "EUR"
}]
}'await fetch(`${process.env.TRACELOG_API}/v1/server/events`, {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.TRACELOG_SERVER_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
v: 1,
events: [
{
// UUID v7 generado una vez por pedido y guardado con él. En
// Node, v7() del paquete uuid genera uno; crypto.randomUUID()
// genera un v4, que TraceLog rechaza.
eventId: order.eventId,
sessionId: order.sessionId,
kind: "conversion",
name: "purchase",
occurredAt: new Date().toISOString(),
identifier: order.number,
value: order.total,
currency: order.currency,
},
],
}),
});<?php
// Un UUID v7: milisegundos Unix, versión, variante y bits aleatorios.
function uuid_v7()
{
$ms = (int) floor(microtime(true) * 1000);
$hex = str_pad(dechex($ms), 12, '0', STR_PAD_LEFT);
$hex .= bin2hex(random_bytes(10));
$hex[12] = '7';
$hex[16] = dechex(8 | (hexdec($hex[16]) & 3));
return preg_replace('/^(.{8})(.{4})(.{4})(.{4})/', '$1-$2-$3-$4-', $hex);
}
// Genera los dos una vez, al crear el pedido, y guárdalos con él.
$order['tracelog_event_id'] = uuid_v7();
$order['tracelog_session_id'] = uuid_v7();
// Cuando se confirme el pago:
$curl = curl_init(getenv('TRACELOG_API') . '/v1/server/events');
curl_setopt_array($curl, [
CURLOPT_POST => true,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 10,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ' . getenv('TRACELOG_SERVER_KEY'),
'Content-Type: application/json',
],
CURLOPT_POSTFIELDS => json_encode([
'v' => 1,
'events' => [[
'eventId' => $order['tracelog_event_id'],
'sessionId' => $order['tracelog_session_id'],
'kind' => 'conversion',
'name' => 'purchase',
'occurredAt' => gmdate('Y-m-d\TH:i:s.000\Z'),
'identifier' => (string) $order['number'],
'value' => (float) $order['total'],
'currency' => $order['currency'],
]],
]),
]);
$response = curl_exec($curl);
curl_close($curl);import json, os, urllib.request
request = urllib.request.Request(
f"{os.environ['TRACELOG_API']}/v1/server/events",
method="POST",
headers={
"Authorization": f"Bearer {os.environ['TRACELOG_SERVER_KEY']}",
"Content-Type": "application/json",
},
data=json.dumps({
"v": 1,
"events": [{
# UUID v7 guardado con el pedido
"eventId": order.tracelog_event_id,
"sessionId": session_id,
"kind": "conversion",
"name": "purchase",
"occurredAt": occurred_at,
"identifier": str(order.number),
"value": float(order.total),
"currency": order.currency,
}],
}).encode(),
)
urllib.request.urlopen(request)Reintentos
Reintenta tras un error de red, una respuesta 5xx o un 429 una vez pasado su
Retry-After, siempre con el mismo eventId.
El eventId es la clave de idempotencia: una entrega repetida se guarda y se
cuenta una sola vez. Con un eventId nuevo, el reintento se contaría otra
vez.
Pagos fallidos
Cuando tu backend vea que falla un pago, puede avisar a TraceLog, con la misma clave
de servidor, con un POST a:
https://api.tracelog.io/v1/server/payment-failure
{ "gateway": "redsys", "occurredAt": "2026-11-04T10:15:30.000Z" }gateway es el nombre del método de pago, de 1 a 100 caracteres sin los espacios de
los extremos. occurredAt puede tener como mucho 48 horas de antigüedad y adelantarse
cinco minutos como mucho. TraceLog guarda un recuento por día y pasarela y nada más
del pedido, así que no envíes ni número de pedido, ni importe, ni dirección. Una
tarjeta rechazada y reintentada cuenta dos veces.
204: guardado.400: el cuerpo no es como el de arriba. Surefusalespayment_failure_invalid.401: la clave falta, es desconocida, está revocada o no es la de servidor.409: el proyecto está en Shopify, cuyo pago ya los comunica. Surefusalespayment_failure_channel.429: demasiadas solicitudes con esta clave, el límite que comparte con tus eventos, con una cabeceraRetry-Afteren segundos.503: TraceLog no ha podido guardarlo.