Guía de integraciónAutenticaciónConvenciones de endpointsModelosErroresWebhooks
1tokens1tokens
EmpezarReferencia API

Webhooks

1tokens envía una solicitud POST firmada a la URL HTTPS que registres en la consola cada vez que ocurre un evento suscrito. Crea un endpoint en la página Webhooks y marca los eventos que quieras; los endpoints nuevos entran en vigor en menos de 30 segundos.

Catálogo de eventos

Modelo

TipoNombreCampos de data
model.listedModelo publicadomodel tenant_id previous_status status actor
model.delistedModelo retiradomodel tenant_id previous_status status actor
model.deprecatedModelo obsoletomodel previous_status status actor
model.price.changedPrecio cambiadomodel tenant_id pricing_status sale_price_mode multiplier price changes actor
model.user_price.changedPrecio de usuario cambiadomodel user_id multiplier changes actor
model.updatedModelo actualizadomodel changes actor

API Key

TipoNombreCampos de data
api_key.createdKey creadaapi_key actor
api_key.updatedKey actualizadaapi_key changes actor
api_key.revokedKey revocadaapi_key previous_status status actor
api_key.expiredKey caducadaapi_key actor
api_key.quota.exhaustedCuota agotadaapi_key quota_limit_usd consumed_usd actor
api_key.rate_window.exceededLímite de ventana superadoapi_key window limit_usd consumed_usd actor

Cuenta

TipoNombreCampos de data
account.balance.lowSaldo bajoaccount threshold_usd request_id actor
account.balance.exhaustedSaldo agotadoaccount reason request_id actor
account.credit.topupRecargaaccount amount_usd amount_credits source order_no actor
account.credit.adjustedAjuste de saldoaccount delta_usd delta_credits kind reason actor
account.trial.grantedPrueba concedidaaccount amount_credits actor
account.disabledCuenta desactivadaaccount previous_status status actor
account.enabledCuenta activadaaccount previous_status status actor
account.password.resetContraseña restablecidaaccount actor

Pedido

TipoNombreCampos de data
order.createdPedido creadoorder actor
order.paidPedido pagadoorder paid_at previous_status status actor
order.failedPago fallidoorder reason previous_status status actor
order.redeemedCódigo canjeadoorder code_masked actor

Suscripción

TipoNombreCampos de data
subscription.startedSuscripción iniciadasubscription previous_status status actor
subscription.renewedSuscripción renovadasubscription actor
subscription.upgradedSuscripción mejoradasubscription changes actor
subscription.cancelledSuscripción canceladasubscription previous_status status actor
subscription.payment_failedRenovación fallidasubscription reason actor
subscription.quota.exhaustedCuota agotadasubscription request_id actor

Tarea

TipoNombreCampos de data
task.video.succeededVídeo listotask video_count actor
task.video.failedVídeo fallidotask actor
task.generation.succeededGeneración listatask media output_count actor
task.generation.failedGeneración fallidatask media actor

Contenido

TipoNombreCampos de data
content.changelog.publishedChangelog publicadoentry actor
content.article.publishedArtículo publicadoarticle tenant_id previous_status status actor
content.article.unpublishedArtículo retiradoarticle tenant_id previous_status status actor

Webhook

TipoNombreCampos de data
webhook.endpoint.auto_disabledEndpoint desactivadoendpoint reason consecutive_failures actor

Formato del payload

Todos los eventos comparten el mismo sobre: id (id único del evento), type, domain, created_at (ISO 8601 UTC), api_version y data. Dentro de data las claves van en snake_case, las fechas terminan en _at, los importes son cadenas decimales (_usd / _credits) y los valores ausentes son null explícitos. Un mismo evento puede entregarse más de una vez por los reintentos; deduplica por id.

{  "id": "evt_01JBXK6Q3N7Y8R2V4W5X6Z7A8B",  "type": "model.price.changed",  "domain": "model",  "created_at": "2026-11-04T08:12:33Z",  "api_version": "2026-11-04",  "data": { }}

Cabeceras de la solicitud

POST https://your-server.example/webhooksContent-Type: application/jsonUser-Agent: Webhooks/1.0X-Event-Id: evt_01JBXK6Q3N7Y8R2V4W5X6Z7A8BX-Event-Type: model.price.changedX-Delivery-Id: 123456X-Timestamp: 1762243953X-Signature: v1=5f1c…

Verificar la firma

Calcula HMAC-SHA256 con el secreto mostrado al crear el endpoint sobre la cadena valor de X-Timestamp + . + cuerpo crudo de la solicitud, y compáralo en tiempo constante con el hexadecimal que sigue a v1= en X-Signature. Rechaza las solicitudes cuya marca de tiempo difiera de la actual en más de 5 minutos. Responde 2xx primero y procesa después; toda la respuesta debe completarse en menos de 10 segundos.

import { createHmac, timingSafeEqual } from "node:crypto";export function verify(secret, headers, rawBody) {  const ts = headers["x-timestamp"];  if (Math.abs(Date.now() / 1000 - Number(ts)) > 300) return false;  const expected = createHmac("sha256", secret).update(ts + "." + rawBody).digest("hex");  const given = String(headers["x-signature"]).replace(/^v1=/, "");  return given.length === expected.length && timingSafeEqual(Buffer.from(given, "hex"), Buffer.from(expected, "hex"));}
import hmac, hashlib, timedef verify(secret: str, headers: dict, raw_body: bytes) -> bool:    ts = headers["X-Timestamp"]    if abs(time.time() - int(ts)) > 300:        return False    expected = hmac.new(secret.encode(), f"{ts}.".encode() + raw_body, hashlib.sha256).hexdigest()    given = headers["X-Signature"].removeprefix("v1=")    return hmac.compare_digest(given, expected)
func verify(secret string, ts, sig string, body []byte) bool {	t, _ := strconv.ParseInt(ts, 10, 64)	if math.Abs(float64(time.Now().Unix()-t)) > 300 {		return false	}	mac := hmac.New(sha256.New, []byte(secret))	mac.Write([]byte(ts + "."))	mac.Write(body)	expected := hex.EncodeToString(mac.Sum(nil))	return hmac.Equal([]byte(strings.TrimPrefix(sig, "v1=")), []byte(expected))}

Reintentos y desactivación automática

Una respuesta distinta de 2xx o la ausencia de respuesta en 10 segundos cuenta como fallo. Cada entrega se intenta hasta 7 veces con los intervalos de la tabla; después se marca como agotada. Un endpoint con 10 entregas consecutivas agotadas se desactiva automáticamente y se te avisa por correo; vuelve a activarlo en la consola cuando lo hayas corregido. Cualquier entrega puede reenviarse manualmente desde la consola.

IntentoEspera tras el anterior
10
21 min
35 min
430 min
52 h
66 h
724 h

Requisitos del endpoint

La URL debe ser una dirección HTTPS accesible públicamente; se rechazan los nombres de host que resuelven a rangos privados, de loopback o de enlace local. No se siguen redirecciones y se leen como máximo 64 KB del cuerpo de la respuesta.

Errores

Previous Page

On this page

Catálogo de eventosModeloAPI KeyCuentaPedidoSuscripciónTareaContenidoWebhookFormato del payloadCabeceras de la solicitudVerificar la firmaReintentos y desactivación automáticaRequisitos del endpoint
{
  "id": "evt_01JBXK6Q3N7Y8R2V4W5X6Z7A8B",
  "type": "model.price.changed",
  "domain": "model",
  "created_at": "2026-11-04T08:12:33Z",
  "api_version": "2026-11-04",
  "data": { }
}
POST https://your-server.example/webhooks
Content-Type: application/json
User-Agent: Webhooks/1.0
X-Event-Id: evt_01JBXK6Q3N7Y8R2V4W5X6Z7A8B
X-Event-Type: model.price.changed
X-Delivery-Id: 123456
X-Timestamp: 1762243953
X-Signature: v1=5f1c…
import { createHmac, timingSafeEqual } from "node:crypto";

export function verify(secret, headers, rawBody) {
  const ts = headers["x-timestamp"];
  if (Math.abs(Date.now() / 1000 - Number(ts)) > 300) return false;
  const expected = createHmac("sha256", secret).update(ts + "." + rawBody).digest("hex");
  const given = String(headers["x-signature"]).replace(/^v1=/, "");
  return given.length === expected.length && timingSafeEqual(Buffer.from(given, "hex"), Buffer.from(expected, "hex"));
}
import hmac, hashlib, time

def verify(secret: str, headers: dict, raw_body: bytes) -> bool:
    ts = headers["X-Timestamp"]
    if abs(time.time() - int(ts)) > 300:
        return False
    expected = hmac.new(secret.encode(), f"{ts}.".encode() + raw_body, hashlib.sha256).hexdigest()
    given = headers["X-Signature"].removeprefix("v1=")
    return hmac.compare_digest(given, expected)
func verify(secret string, ts, sig string, body []byte) bool {
	t, _ := strconv.ParseInt(ts, 10, 64)
	if math.Abs(float64(time.Now().Unix()-t)) > 300 {
		return false
	}
	mac := hmac.New(sha256.New, []byte(secret))
	mac.Write([]byte(ts + "."))
	mac.Write(body)
	expected := hex.EncodeToString(mac.Sum(nil))
	return hmac.Equal([]byte(strings.TrimPrefix(sig, "v1=")), []byte(expected))
}