Referencia API

Webhooks

Cabeceras de entrega, payloads de eventos, reintentos y registros de entrega.

URL de callback

Configura la URL de callback del equipo en los ajustes de integración de desarrollador. MakePay revisa primero la configuración de producto MakePay y luego la configuración compartida de callback de desarrollador, para que los ajustes existentes de webhooks MakeSwap puedan recibir eventos de pago MakePay mientras se despliega la configuración específica del producto.

Cuando guardas una URL de callback MakePay, MakeCrypto genera un secreto de webhook. Guárdalo en el gestor de secretos de tu backend. Puedes regenerarlo en cualquier momento desde la misma pantalla de ajustes; después de regenerarlo, actualiza tu backend antes de exigir firmas con el nuevo secreto.

Comportamiento de entrega

MakePay envía webhooks de pago y suscripción como solicitudes POST con cuerpo JSON. Las entregas fallidas se reintentan hasta diez veces a intervalos de cinco minutos. El reenvío manual está disponible desde los registros de solicitudes de webhook de MakeCrypto.

Cabeceras

content-type: application/json
user-agent: MakePay-Webhooks/1.0
x-makepay-delivery-id: 9f1c6cf4-8514-4ee5-80fd-8e8fe2b5e313
x-makepay-delivery-group-id: 9f1c6cf4-8514-4ee5-80fd-8e8fe2b5e313
x-makepay-delivery-origin: event
x-makepay-event: status_changed
x-makepay-attempt: 1
x-makepay-signature: t=1776556800,v1=7d4b3f...

Verificar firmas

MakePay firma el cuerpo JSON bruto exacto con HMAC-SHA256. El payload de firma es:

{timestamp}.{raw_request_body}

La cabecera x-makepay-signature contiene el timestamp Unix y el digest versionado:

t=1776556800,v1=<hex_hmac_sha256>

Ejemplo de verificación en Node.js:

import crypto from "node:crypto";

const WEBHOOK_SECRET = process.env.MAKEPAY_WEBHOOK_SECRET!;
const TOLERANCE_SECONDS = 300;

export function verifyMakePayWebhook(input: {
  rawBody: string;
  signatureHeader: string | null;
}) {
  if (!input.signatureHeader) {
    return false;
  }

  const parts = Object.fromEntries(
    input.signatureHeader.split(",").map((part) => {
      const [key, value] = part.trim().split("=");
      return [key, value];
    }),
  );

  const timestamp = Number(parts.t);
  const signature = parts.v1;

  if (!Number.isFinite(timestamp) || !signature) {
    return false;
  }

  const now = Math.floor(Date.now() / 1000);
  if (Math.abs(now - timestamp) > TOLERANCE_SECONDS) {
    return false;
  }

  const expected = crypto
    .createHmac("sha256", WEBHOOK_SECRET)
    .update(`${timestamp}.${input.rawBody}`, "utf8")
    .digest("hex");
  const actualBuffer = Buffer.from(signature, "hex");
  const expectedBuffer = Buffer.from(expected, "hex");

  return (
    actualBuffer.length === expectedBuffer.length &&
    crypto.timingSafeEqual(actualBuffer, expectedBuffer)
  );
}

Lee el cuerpo bruto antes de parsear JSON. Si tu framework parsea el cuerpo primero, configura la ruta de webhook para exponer los bytes brutos y verifica esos bytes antes de confiar en el payload.

Payload de pago

{
  "deliveryId": "9f1c6cf4-8514-4ee5-80fd-8e8fe2b5e313",
  "type": "makepay.payment.status_changed",
  "createdAt": "2026-04-19T00:00:00.000Z",
  "event": {
    "type": "status_changed",
    "trigger": "payment_status_reconcile"
  },
  "paymentLink": {
    "id": "8d15bb78-d0f8-45ef-88d7-2a1f1f79644b",
    "uid": "01hzy4k6p4w9y2x7e2z7n8a2xm",
    "status": "active",
    "publicUrl": "https://makepay.io/payment/01hzy4k6p4w9y2x7e2z7n8a2xm",
    "expiresAt": "2026-04-19T12:00:00.000Z",
    "amount": "129.99",
    "currency": "USDT",
    "asset": "ETH.USDT-0xdac17f958d2ee523a2206206994597c13d831ec7",
    "label": "Website order #1042",
    "description": "Checkout for order #1042",
    "merchantOrderId": "order_1042",
    "clientEmail": "buyer@example.com",
    "clientId": null
  },
  "session": {
    "id": "5b55f0bb-0ac4-4f7c-a1d1-0d9af19c3bbd",
    "status": "complete",
    "previousStatus": "pending",
    "invoiceAsset": "USDT",
    "invoiceAmount": "129.99",
    "selectedSellAsset": "ETH",
    "requiredSellAmount": "0.04",
    "expectedBuyAmount": "129.99",
    "destinationAddress": "0xmerchant...",
    "depositAddress": "0xdeposit...",
    "channelId": "channel_123",
    "compositeChannelId": "ETH:channel_123",
    "sourceChain": "ETH",
    "expiresAt": "2026-04-19T00:30:00.000Z",
    "settlement": {},
    "errorMessage": null
  }
}

Tipos de evento

  • status_changed para cambios de estado de la sesión de pago.
  • settlement_updated cuando cambian datos de liquidación tras la conciliación de estado.
  • payment_request_expired, quote_expired y payment_cancelled_by_payer para resultados terminales sin pago.
  • channel_created cuando el pagador acepta una cotización y MakePay crea el canal de depósito.
  • subscription_status_changed cuando una suscripción MakePay se mueve entre active, paused, overdue o cancelled.

quote_created y quote_refreshed son eventos internos del timeline de pago y no se envían a URLs de callback.

Payload de estado de suscripción

MakePay también envía un callback cuando cambia el estado de una suscripción. El scheduler marca una suscripción como overdue cuando el ciclo de facturación impago más antiguo lleva al menos 24 horas pasado su dueAt; cuando ningún ciclo impago supera esas 24 horas, el scheduler vuelve a mover la suscripción a active. Los cambios de estado desde merchant y portal de cliente usan el mismo callback.

{
  "deliveryId": "78c35c42-61fb-4dd3-94b7-2a7df998bb6f",
  "type": "makepay.subscription.status_changed",
  "createdAt": "2026-04-20T00:00:00.000Z",
  "event": {
    "type": "subscription_status_changed",
    "trigger": "subscription_scheduler"
  },
  "subscription": {
    "id": "f6b76460-a437-4a81-a59f-8fcbb18c0f0f",
    "uid": "sub_premium_001",
    "status": "overdue",
    "previousStatus": "active",
    "customerEmail": "buyer@example.com",
    "label": "Premium plan",
    "description": "Monthly subscription",
    "amountUsd": "49.99",
    "settlementAsset": "ETH.USDT-0xdac17f958d2ee523a2206206994597c13d831ec7",
    "cadence": "monthly",
    "billingIntervalUnit": "month",
    "billingIntervalCount": 1,
    "startAt": "2026-04-18T00:00:00.000Z",
    "timezone": "Asia/Dubai",
    "metadata": {
      "clientId": "client_1042"
    },
    "createdAt": "2026-04-18T00:00:00.000Z",
    "updatedAt": "2026-04-20T00:00:00.000Z"
  },
  "cycle": {
    "id": "f303b3b3-26d8-42bc-8c10-91fa1445f507",
    "subscriptionId": "f6b76460-a437-4a81-a59f-8fcbb18c0f0f",
    "sequence": 0,
    "dueAt": "2026-04-18T00:00:00.000Z",
    "amountUsd": "49.99",
    "paymentLinkId": "8d15bb78-d0f8-45ef-88d7-2a1f1f79644b",
    "paymentLinkUid": "01hzy4k6p4w9y2x7e2z7n8a2xm",
    "paymentUrl": "https://makepay.io/payment/01hzy4k6p4w9y2x7e2z7n8a2xm",
    "status": "overdue"
  },
  "data": {
    "previousStatus": "active",
    "nextStatus": "overdue",
    "reason": "cycle_one_day_overdue"
  }
}

API de registros de entrega

Usa la ruta de solicitudes de webhook para inspeccionar entregas y reintentos.

GET /api/partner/v1/makepay/webhook-requests?limit=100

Los filtros opcionales incluyen paymentLinkUid, deliveryStatus y search.

¿Necesitas ayuda con la configuración de partner?

Abre la vista de detalles del enlace de pago en MakeCrypto para copiar los snippets generados para un UID de pago real, o vuelve al portal para gestionar la configuración del merchant.

Abrir portal