Presentación
Un webhook es una dirección de internet (una URL) que pertenece a su organización: la de su servidor, la de su CRM o la de una herramienta como Make o Zapier. En cuanto se produce un evento en Donoor, Donoor envía a esa dirección una solicitud HTTPS POST que describe el evento en formato JSON.
Cada mensaje se firma con un secreto que solo usted conoce: así su servidor puede verificar que procede realmente de Donoor y que no ha sido modificado. Si su servidor no responde, Donoor vuelve a intentarlo automáticamente durante unas 28 horas.
Se produce un evento
donación, afiliación, entrada…
Donoor envía un mensaje firmado
POST · Donoor-Signature
Su servidor
verifica, responde 200, procesa
Publicidad — transmitir cada donación como conversión a Google Ads, GA4 o Meta, con la campaña de origen.
CRM — crear o actualizar la ficha del donante, del socio o del comprador.
Contabilidad — registrar pagos, reembolsos, recibos fiscales y transferencias bancarias.
Automatización — avisar a su equipo, rellenar una hoja de cálculo, enviar un correo electrónico de bienvenida.
Inicio rápido
Cuente con unos quince minutos para recibir su primer mensaje.
- 1
Prepare una dirección de recepción
Una dirección https accesible desde Internet, en su servidor o en una herramienta como Make o Zapier. Para probar sin instalar nada, basta con una dirección gratuita de webhook.site.
- 2
Añádala en su panel
Ajustes › Webhooks › Añadir una dirección. Asígnele una descripción y elija los eventos que desea recibir (todos, por defecto).
- 3
Copie el secreto
Empieza por whsec_. Guárdelo en la configuración de su servidor, nunca en una página web ni en un repositorio de código público.
- 4
Verifique la firma y responda 200
Su servidor verifica el encabezado Donoor-Signature y después responde con un código 2xx en menos de 10 segundos. El código listo para copiar está más abajo, en Node.js, PHP y Python.
- 5
Envíe un mensaje de prueba
Botón Enviar una prueba, o Simular un evento para recibir cualquiera de los 28 eventos con datos ficticios. Después, compruebe el resultado en el registro de envíos.
Solo se envían los eventos que se producen después de añadir su primera dirección: el historial no se reenvía. Los mensajes contienen el correo electrónico y el nombre de los donantes: solo el responsable y los administradores de la organización pueden gestionar los webhooks, y el responsable recibe un correo electrónico cada vez que se añade o modifica una dirección.
Lista de eventos
Cada dirección recibe los eventos que usted ha marcado. La columna «Contenido» indica los objetos presentes en data, descritos en la sección Objetos.
Pagos
| Tipo | Enviado cuando… | Contenido |
|---|---|---|
payment.succeeded | Se confirma un pago: donación puntual o mensual (primer pago y cada renovación), afiliación, entrada, pedido de tienda, código QR, colecta, Tap to Pay. | paymentattribution |
payment.failed | Se rechaza una tarjeta o un cargo, por ejemplo la renovación de una donación mensual. | paymentattribution |
payment.refunded | Se reembolsa un pago, total o parcialmente. Un mensaje por reembolso. | paymentrefundattribution |
dispute.opened | Un donante disputa un pago ante su banco. | paymentdisputeattribution |
dispute.closed | La disputa se cierra, ganada o perdida. | paymentdisputeattribution |
Donaciones mensuales
| Tipo | Enviado cuando… | Contenido |
|---|---|---|
subscription.created | Un donante inicia una donación mensual. | subscriptionattribution |
subscription.past_due | El cargo del mes no se ha cobrado: la donación mensual está pendiente de pago. | subscriptionattribution |
subscription.reactivated | Una donación mensual impagada vuelve a estar al día. | subscriptionattribution |
subscription.canceled | Se detiene una donación mensual. | subscriptionattribution |
Pedidos (afiliaciones, venta de entradas, tienda)
| Tipo | Enviado cuando… | Contenido |
|---|---|---|
order.confirmed | Se confirma una afiliación, unas entradas o una compra en la tienda, incluso cuando son gratuitas. | order |
order.pending_approval | Una solicitud de afiliación espera su validación. | order |
order.rejected | Usted ha rechazado una solicitud de afiliación. | order |
order.canceled | Se cancela un pedido. | order |
order.expired | Un pedido no se pagó a tiempo y ha caducado. | order |
order.fulfillment_updated | Un pedido de la tienda cambia de etapa: en preparación, enviado (con el número de seguimiento), entregado o recogido. | order |
Socios y entradas
| Tipo | Enviado cuando… | Contenido |
|---|---|---|
membership.created | Un carné de socio pasa a estar activo. | membership |
membership.canceled | Se cancela una afiliación. | membership |
ticket.checked_in | Se escanea una entrada en el acceso a su evento. | ticket |
ticket.canceled | Se cancela una entrada. | ticket |
Solicitudes de reembolso
| Tipo | Enviado cuando… | Contenido |
|---|---|---|
refund_request.created | Un donante o un comprador le solicita un reembolso. | refund_request |
refund_request.updated | Una solicitud de reembolso cambia de estado: respondida, reembolsada o rechazada. | refund_request |
Recibos fiscales
| Tipo | Enviado cuando… | Contenido |
|---|---|---|
fiscal_receipt.issued | Se emite un recibo fiscal para un donante. | fiscal_receipt |
fiscal_receipt.voided | Se anula un recibo fiscal, por ejemplo tras un reembolso. | fiscal_receipt |
Transferencias bancarias
| Tipo | Enviado cuando… | Contenido |
|---|---|---|
payout.paid | Stripe o PayPal ha transferido dinero a la cuenta bancaria de la organización. | payout |
payout.failed | Ha fallado una transferencia a la cuenta bancaria de la organización. | payout |
Formularios y colectas
| Tipo | Enviado cuando… | Contenido |
|---|---|---|
form.created | Se crea una colecta, un evento, una modalidad de afiliación, una tienda, un enlace de pago o un código QR. | form |
campaign.goal_reached | Una colecta alcanza su objetivo. | campaign |
Cuenta de la organización
| Tipo | Enviado cuando… | Contenido |
|---|---|---|
organization.payment_account_updated | La cuenta de Stripe o PayPal de la organización se activa o se suspende. | payment_account |
Prueba
| Tipo | Enviado cuando… | Contenido |
|---|---|---|
test.ping | Mensaje de prueba enviado desde el panel. | message |
Un pedido pagado desencadena dos eventos: order.confirmed (el pedido) y payment.succeeded (el dinero). Para medir sus conversiones, utilice solo payment.succeeded; para gestionar sus inscritos, solo order.confirmed. Suscriba cada dirección únicamente a los eventos que necesite.
Los mensajes suelen enviarse menos de dos minutos después del hecho: Donoor espera a que toda la información sea definitiva (importe abonado, comisiones…) antes de enviarlos.
Estructura de un mensaje
Cada mensaje es una solicitud POST cuyo cuerpo JSON, codificado en UTF-8, tiene siempre el mismo envoltorio. Solo el contenido de data cambia según el tipo de evento. Los nombres de los campos están en inglés, como en Stripe o HelloAsso.
| Campo | Tipo | Descripción |
|---|---|---|
id | string | Identificador único del evento (evt_…). Se mantiene igual en cada reintento y en cada reenvío: es lo que permite ignorar un duplicado. |
object | string | Siempre event. |
type | string | Tipo del evento, por ejemplo payment.succeeded. |
api_version | string | Versión del formato del mensaje. Solo cambia ante una evolución incompatible. |
created | string (ISO 8601) | Fecha de creación del evento, en UTC. |
livemode | boolean | true para un evento real; false para una simulación o en el entorno de pruebas. No cuente nunca un mensaje con livemode false como un pago real. |
organization | object | La organización afectada: id (número Donoor) y name. |
data | object | Los objetos propios del evento: payment, order, ticket… (ver Objetos). |
Ejemplos de mensajes
{
"id": "evt_9mK2xQpL4vR8sT1w",
"object": "event",
"type": "payment.succeeded",
"api_version": "2026-10-17",
"created": "2026-10-17T14:02:11.000Z",
"livemode": true,
"organization": {
"id": 1234,
"name": "Les Amis du Quartier"
},
"data": {
"payment": {
"id": 32631,
"conversion_id": "32631",
"order_id": null,
"status": "succeeded",
"amount": 50.6,
"amount_cents": 5060,
"net_amount": 49.3,
"fees_covered_amount": 0.6,
"provider_fee_amount": 1.3,
"currency": "EUR",
"refunded_amount": 0,
"kind": "donation",
"channel": "online",
"form": null,
"recurring": {
"interval": "month",
"sequence": "first",
"subscription_id": 812
},
"payment_provider": "stripe",
"payment_method": "card",
"wallet": "apple_pay",
"provider_reference": "pi_3UQZvoFXPodLa3BZ2HKqlaEw",
"donor": {
"email": "amina.k@exemple.fr",
"name": "Amina K.",
"anonymous": false
},
"created": "2026-10-17T14:01:02.000Z"
},
"attribution": {
"parameters": {
"utm_source": "google",
"utm_medium": "cpc",
"utm_campaign": "ramadan-2027",
"gclid": "Cj0KCQjw8eTFBhCXARIsAIkiuOz"
},
"landing_page": "https://www.mon-association.org/faire-un-don",
"marketing_consent": true
}
}
}Objetos
Los objetos que pueden aparecer en data. Un campo sin valor es null. Las fechas están en formato ISO 8601, en UTC.
Todos los importes están en euros, con dos decimales; los campos …_cents indican el mismo importe en céntimos. Los importes son los de la organización: la aportación opcional que un donante deja a Donoor nunca figura en ellos.
idinteger | Identificador Donoor del pago. |
conversion_idstring | Identificador de conversión, que debe transmitirse a Google y Meta. Igual a id para una donación, y al número de pedido para una afiliación, una entrada o una compra en la tienda. Es también el transaction_id que el widget envía al dataLayer. |
order_idstring | null | Identificador del pedido vinculado (afiliación, venta de entradas, tienda); null en caso contrario. |
statusstring | succeeded, failed, refunded, partially_refunded o disputed. |
amountnumber | Importe pagado para la organización, comisiones cubiertas por el donante incluidas. Es el valor que debe enviarse como conversión. |
amount_centsinteger | El mismo importe, en céntimos. |
net_amountnumber | null | Importe realmente abonado a la organización por Stripe o PayPal, tras sus comisiones. null mientras el proveedor no lo haya comunicado. |
fees_covered_amountnumber | Parte de las comisiones que el donante ha decidido asumir (0 en caso contrario). |
provider_fee_amountnumber | null | Comisiones retenidas por Stripe o PayPal, tal como las indican. |
currencystring | Moneda, código ISO 4217 en mayúsculas (EUR). |
refunded_amountnumber | Total ya reembolsado de este pago. |
kindstring | Naturaleza del pago: donation, membership, ticket o shop. |
channelstring | Canal: online (página de donación, widget), campaign (colecta), qr_code, tap_to_pay u offline (pago introducido manualmente). |
formobject | null | El formulario de origen: type (campaign, event, membership_plan, shop, qr_code), id y title. null para una donación en la página de donación. |
recurringobject | null | Para una donación mensual: interval, sequence (first para el primer pago, renewal para los siguientes) y subscription_id. null en caso contrario. |
payment_providerstring | stripe, paypal o manual. |
payment_methodstring | null | Medio de pago indicado por el proveedor: card, sepa_debit, card_present (Tap to Pay), paypal… |
walletstring | null | apple_pay o google_pay cuando el donante ha pagado con ellos; null en caso contrario. |
provider_referencestring | null | Referencia del pago en el proveedor (pi_… en Stripe, número de pedido en PayPal). |
donorobject | El donante: email, name y anonymous (true si ha pedido permanecer anónimo en la página pública; usted recibe igualmente sus datos de contacto). |
createdstring (ISO 8601) | Fecha del pago. |
Encabezados HTTP
Cada solicitud lleva estos encabezados. Los nombres de los encabezados HTTP no distinguen entre mayúsculas y minúsculas: su servidor puede recibirlos en minúsculas.
| Encabezado | Descripción |
|---|---|
Content-Typeapplication/json | El cuerpo es JSON codificado en UTF-8. |
User-AgentDonoor-Webhooks/1.0 (+https://donoor.org/developpeurs/webhooks) | Identifica a Donoor. No lo utilice para autenticar: solo la firma da fe. |
Donoor-Signaturet=1792300000,v1=f0f590ea41b7… | Marca de tiempo y firma del mensaje (ver Verificar la firma). |
Donoor-Event-Idevt_9mK2xQpL4vR8sT1w | Idéntico al campo id del cuerpo: práctico para descartar un duplicado incluso antes de leer el JSON. |
Donoor-Event-Typepayment.succeeded | Idéntico al campo type del cuerpo. |
Donoor-Delivery-Attempt1 | Número del intento: 1 para el primer envío, hasta 8. |
Verificar la firma
Cualquiera puede enviar una solicitud a su dirección: por eso, verifique siempre la firma antes de confiar en un mensaje. El encabezado Donoor-Signature contiene la marca de tiempo del envío (t, en segundos) y una o dos firmas v1. Cada firma es un HMAC-SHA256, escrito en hexadecimal, del texto «marca de tiempo + punto + cuerpo bruto», calculado con su secreto.
Donoor-Signature: t=1792300000,v1=f0f590ea41b7f691921bb57c47f593d785d4e4d7d6c14f947848cb9d2d471bdf- 1
Lea el cuerpo BRUTO de la solicitud, byte a byte, antes de cualquier decodificación JSON.
- 2
Obtenga t y todos los valores v1 del encabezado Donoor-Signature.
- 3
Calcule HMAC-SHA256 con su secreto (whsec_ incluido) sobre t + «.» + cuerpo y compare después el resultado con cada v1 mediante una comparación en tiempo constante. Basta con que coincida uno.
- 4
Rechace el mensaje si t difiere en más de 5 minutos de su reloj: así, un mensaje interceptado no puede reproducirse más tarde.
// Node.js (Express) — el cuerpo BRUTO es imprescindible para la firma
import crypto from "node:crypto";
import express from "express";
const SECRET = process.env.DONOOR_WEBHOOK_SECRET; // whsec_…
const app = express();
app.post("/webhooks/donoor", express.raw({ type: "application/json" }), (req, res) => {
const entete = req.get("Donoor-Signature") ?? "";
const t = /t=(\d+)/.exec(entete)?.[1];
const signatures = [...entete.matchAll(/v1=([0-9a-f]{64})/g)].map((m) => m[1]);
const attendue = crypto.createHmac("sha256", SECRET).update(`${t}.${req.body}`).digest("hex");
const valide = signatures.some((s) =>
crypto.timingSafeEqual(Buffer.from(s, "hex"), Buffer.from(attendue, "hex")));
const recent = t && Math.abs(Date.now() / 1000 - Number(t)) < 300;
if (!valide || !recent) return res.status(400).end();
const evenement = JSON.parse(req.body.toString("utf8"));
res.status(200).end(); // responder rápido, procesar después
traiter(evenement); // procesar el evento; ignorarlo si su id ya se ha visto
});Ejemplo de verificación
Para probar su código sin esperar a un mensaje real: con estos valores, debe obtener exactamente esta firma.
| Secreto | whsec_5wQpK9mZ2vX7rT4yN8bH3jL6fD1sA0cE |
| Marca de tiempo (t) | 1792300000 |
| Cuerpo bruto | {"id":"evt_doc0exemple0signature","object":"event","type":"test.ping"} |
| Firma v1 esperada | f0f590ea41b7f691921bb57c47f593d785d4e4d7d6c14f947848cb9d2d471bdf |
El error más frecuente: firmar el JSON después de decodificarlo y volver a codificarlo. El más mínimo espacio o el orden de las claves cambia la firma. Firme siempre el cuerpo exactamente tal como lo recibió.
Cambiar el secreto
Si otra persona ha podido ver su secreto, sustitúyalo: Ajustes › Webhooks › Secreto › Cambiar el secreto.
Durante 24 horas, los mensajes se firman con el secreto antiguo Y con el nuevo: el encabezado contiene entonces dos valores v1. Instale el nuevo secreto en su servidor durante ese plazo; después, solo funciona el nuevo.
Donoor conserva el secreto cifrado. Solo se muestra a los responsables y administradores de la organización.
Direcciones aceptadas
- Solo direcciones https, con un certificado válido.
- Puerto 443 (el predeterminado) u 8443.
- La dirección debe ser accesible desde Internet: las direcciones locales o privadas (localhost, red interna) se rechazan.
- Las redirecciones no se siguen: una respuesta 3xx cuenta como fallo. Indique la dirección final.
- Donoor no envía desde una lista fija de direcciones IP: no filtre por IP, verifique la firma.
Responder a un mensaje
Responda con un código 2xx (200, 201, 204…) en menos de 10 segundos. El contenido de su respuesta no se lee, pero su comienzo se muestra en el registro de envíos para ayudarle a depurar.
Responda primero y procese después: guarde el mensaje, responda 200 y realice los procesos largos (llamada a Google Ads, envío de correo electrónico…) en segundo plano.
| Respuesta de su servidor | Lo que hace Donoor |
|---|---|
| 2xx | Éxito: el mensaje se marca como correcto en el registro. |
| 3xx | Fallo (redirección no seguida): nuevo intento más tarde. |
| 4xx, 5xx | Fallo: nuevo intento más tarde. |
| sin respuesta | Más de 10 segundos, conexión rechazada o certificado no válido: fallo, nuevo intento más tarde. |
Reintentos y pausa
Cuando un envío falla, Donoor vuelve a intentarlo automáticamente: 8 intentos en total, a lo largo de unas 28 horas.
- 1.er envío
- +1 min
- +5 min
- +30 min
- +2 h
- +5 h
- +10 h
- +10 h
- Tras el 8.º intento, el mensaje se abandona y la organización recibe un aviso por correo electrónico (como máximo un correo por dirección y por día).
- Una dirección que no acepta ningún mensaje durante 3 días se pone en pausa automáticamente, con un aviso por correo electrónico. Se reactiva con un clic en el panel.
- Cualquier mensaje del registro puede reenviarse manualmente durante 30 días: botón Reenviar.
Duplicados y orden
Un mismo evento puede llegar más de una vez: su servidor procesó el mensaje pero su respuesta se perdió, o alguien hizo clic en Reenviar. El evento conserva entonces el mismo id: guarde los id ya procesados e ignore los que ya conoce.
El orden de llegada no está garantizado: en caso de reintento, un reembolso puede llegar antes que el pago original. Básese en el campo created y en los estados de los objetos, no en el orden de recepción.
Para una conversión publicitaria, basta con conversion_id: Google y Meta ignoran por sí mismos una conversión ya recibida con el mismo identificador.
Límites
| Direcciones por organización | 5 |
| Tiempo máximo de respuesta | 10 segundos |
| Intentos por mensaje | 8, en unas 28 h |
| Pausa automática | tras 3 días sin éxito |
| Mensajes de prueba | 20 por hora |
| Simulaciones | 60 por hora |
| Reenvíos manuales | 100 por hora |
| Mensajes por día | 20.000 por organización |
| Conservación del registro de envíos | 30 días |
| Conservación de la procedencia | 400 días |
Medir sus campañas
El mensaje payment.succeeded le proporciona el importe, la moneda, el identificador de conversión y los parámetros del anuncio de origen. Su servidor transmite después la conversión a la plataforma publicitaria: es fiable incluso cuando el navegador bloquea las cookies o los rastreadores.
Google Analytics 4
Envíe un evento purchase mediante el Measurement Protocol: transaction_id = conversion_id, value = amount, currency = currency.
Google Ads
Con gclid (o gbraid / wbraid) en attribution.parameters: importe una conversión sin conexión mediante la API de Google Ads, con order_id = conversion_id para evitar duplicados. Las conversiones mejoradas pueden utilizar el correo electrónico del donante, con hash SHA-256.
Meta (Facebook, Instagram)
Mediante la Conversions API: event_name = Purchase, event_id = conversion_id, value y currency; fbc se construye con fbclid. El correo electrónico del donante se envía con hash SHA-256.
Sin desarrollador
Pegue la dirección de un escenario de Make o Zapier (módulo «Webhook personalizado»): después podrá conectarlo a Google Ads, GA4, Meta, Google Sheets o a su CRM, sin escribir código.
Widget en su sitio web
Cuando la donación se realiza en el widget de Donoor integrado en su sitio web, la página también recibe el evento donoor_payment en el dataLayer de Google Tag Manager, sin ningún dato personal, con el mismo transaction_id que conversion_id: navegador y servidor solo cuentan una conversión.
CRM y herramientas internas
Utilice donor.email como clave para encontrar la ficha, kind para saber si se trata de una donación, una afiliación, una entrada o una compra, y recurring para identificar a sus donantes mensuales.
Ejemplo: una donación transmitida a GA4
POST https://www.google-analytics.com/mp/collect?measurement_id=G-XXXXXXX&api_secret=…
{
"client_id": "donoor.32631",
"events": [{
"name": "purchase",
"params": {
"transaction_id": "32631", // data.payment.conversion_id
"value": 50.6, // data.payment.amount
"currency": "EUR", // data.payment.currency
"campaign": "ramadan-2027" // data.attribution.parameters.utm_campaign
}
}]
}Procedencia de los pagos
Añada sus parámetros de seguimiento al enlace de sus anuncios, tanto si lleva a su página de Donoor como a la página de su sitio web que muestra el widget de Donoor:
https://donoor.org/pay/mon-association?utm_source=google&utm_campaign=ramadan-2027&gclid=Cj0KCQjw…- Todos los parámetros del enlace se conservan hasta el pago, incluso si el donante abre la página de pago en una nueva pestaña.
- Llegan en data.attribution de payment.succeeded y de los demás eventos del mismo pago (reembolso, disputa, donación mensual).
- Para la renovación de una donación mensual, la procedencia es la del primer pago.
- Los parámetros que parecen datos sensibles (correo electrónico, contraseña, token, teléfono, IBAN…) y los parámetros técnicos de Donoor se descartan. Como máximo 25 parámetros y 300 caracteres por valor.
- attribution es null cuando el donante no llegó a través de un enlace con parámetros.
Consentimiento
attribution.marketing_consent indica si el donante aceptó las cookies publicitarias en Donoor: true, false, o null si se desconoce.
En Europa, Google y Meta exigen respetar esta elección (modo de consentimiento de Google, RGPD). Su organización sigue siendo responsable del uso que haga de estos datos: no envíe el correo electrónico de un donante que las haya rechazado y recuerde mencionar este tratamiento en su política de privacidad.
Pruebas, simulaciones y registro
El botón Enviar una prueba, disponible en cada dirección, envía inmediatamente un evento test.ping firmado como los demás. Sirve para comprobar que su servidor es accesible y que su verificación de la firma es correcta.
El botón Simular un evento, en cada dirección, envía cualquiera de los 28 eventos en el formato exacto, con datos ficticios y livemode en false, solo a esa dirección. Una vista previa muestra el mensaje antes del envío. No se realiza ningún pago ni se envía ningún dato real.
Para desarrollar con tranquilidad, active Dirección de prueba en la ventana de la dirección: entonces solo recibe simulaciones y mensajes de prueba, nunca eventos reales. Conecte a ella el servidor de desarrollo de su equipo y guarde otra dirección para producción.
El registro de envíos muestra cada mensaje de los últimos 30 días: evento, estado, número de intentos, código HTTP y comienzo de la respuesta de su servidor, así como el contenido exacto enviado. Filtre por correctos, fallidos o pendientes, y reenvíe un mensaje con un clic.
Entorno de pruebas
El simulador basta para desarrollar sus webhooks. Para probar también el recorrido de pago completo (página de donación, tarjeta de prueba, recibo), Donoor ofrece un entorno de pruebas separado en sandbox.donoor.org. Sus páginas no están indexadas por los motores de búsqueda.
| Producción | Pruebas | |
|---|---|---|
| Sitio web | donoor.org | sandbox.donoor.org |
| Panel | dashboard.donoor.org | dashboard-sandbox.donoor.org |
| Pagos | reales | ficticios, tarjeta 4242 4242 4242 4242 |
| livemode | true | false |
| Correos electrónicos | normales | asunto precedido de «[TEST]» |
- Cree una cuenta de organización desde sandbox.donoor.org (botón Registrar mi organización): no contiene ningún dato real.
- Conecte Stripe en Ajustes › Proceso de recaudación. En modo de prueba, Stripe acepta información ficticia (código SMS: 000000): no se necesita ninguna cuenta bancaria real.
- Su página de pago de prueba queda en línea de inmediato, por ejemplo sandbox.donoor.org/pay/su-organizacion, al igual que sus colectas, ventas de entradas y tiendas de prueba.
- Añada su dirección de webhook en Ajustes › Webhooks, igual que en producción.
- Haga una donación en esta página con la tarjeta de prueba 4242 4242 4242 4242 (cualquier fecha futura, cualquier código): recibirá mensajes firmados reales, con livemode en false. El secreto de prueba es distinto del de producción.
Versiones del formato
El campo api_version indica la versión del formato del mensaje. Solo cambia en caso de evolución incompatible (un campo renombrado o eliminado, un significado modificado), anunciada con antelación.
Donoor puede, sin cambiar de versión, añadir nuevos eventos y nuevos campos: su código debe ignorar lo que no conozca.
| Versión | Cambios |
|---|---|
| 2026-10-17 | Primera versión pública: 28 eventos, firma HMAC-SHA256, procedencia de los pagos. |
Solución de problemas
No recibo ningún mensaje
Compruebe en el panel que la dirección está Activa y que el evento esperado está marcado; después, envíe un mensaje de prueba: el registro mostrará la respuesta de su servidor o el error encontrado (certificado, tiempo de espera, dirección inaccesible). Su cortafuegos debe aceptar las solicitudes entrantes desde Internet.
La firma nunca coincide
En 9 de cada 10 casos, el cuerpo se ha decodificado y vuelto a codificar antes del cálculo: utilice el cuerpo bruto. Compruebe también que utiliza el secreto completo, prefijo whsec_ incluido, y el de la dirección correcta (cada dirección tiene su propio secreto). El ejemplo de verificación anterior le permite probar su código.
El registro indica una respuesta 301 o 302
Su servidor redirige la solicitud (a menudo de http a https, o a una dirección con o sin barra final). Las redirecciones no se siguen: indique la dirección final exacta.
Recibo dos veces el mismo pago
Es normal en caso de reintento o reenvío: el evento tiene el mismo id, ignórelo. Si los id son diferentes, se trata de dos eventos distintos, por ejemplo order.confirmed y payment.succeeded para el mismo pedido.
No recibo los pagos anteriores a la incorporación de mi dirección
Es intencionado: solo se envían los eventos que se producen después de añadir la primera dirección. Para el historial, utilice las exportaciones del panel.
El importe no coincide con lo que pagó el donante
amount es el importe para la organización: la aportación opcional dejada a Donoor no se incluye; las comisiones cubiertas por el donante, sí. Lo que llega realmente a su cuenta bancaria es net_amount, tras las comisiones de Stripe o PayPal.
¿Tiene alguna pregunta?
Nuestro equipo acompaña a su equipo técnico durante la integración.
Escríbanos