All Docs
FeaturesagentOS Direct DebitUpdated March 13, 2026

Modulr & Griffin Inbound Webhook Handlers

Modulr & Griffin Inbound Webhook Handlers

Introduced in v1.0.39

The Direct Debit service exposes two public webhook endpoints that receive signed event payloads from Modulr and Griffin respectively. These handlers form the real-time nervous system of the fund flow — every mandate lifecycle event and every payment confirmation arrives through one of these routes.


Overview

EndpointProviderPurpose
POST /api/webhooks/modulrModulrMandate status changes, collection outcomes
POST /api/webhooks/griffinGriffinPayment received / payment sent confirmations

Modulr Webhook Handler

Endpoint: POST /api/webhooks/modulr

Supported Events

Mandate Status Changes (AUDDIS)

EventDescription
mandate.auddis_acceptedThe mandate has been accepted by the AUDDIS scheme. The mandate record is updated to active.
mandate.auddis_rejectedThe mandate was rejected during AUDDIS processing. The mandate record is updated to failed and downstream alerting is triggered.

Collection Events

EventDescription
collection.paidFunds have been successfully debited from the tenant's account. Triggers the sweep-to-holding flow.
collection.failedThe collection attempt failed (e.g. insufficient funds). The collection record is updated and an alert is raised.
collection.returnedA previously paid collection has been returned (clawback). The holding account reserve logic is re-evaluated.

Signature Validation

Every inbound request is validated against Modulr's signed payload before processing begins. Requests that fail signature verification receive a 401 Unauthorized response and are not processed further.


Griffin Webhook Handler

Endpoint: POST /api/webhooks/griffin

Supported Events

Payment Received

Fired when funds arrive in the Griffin DD holding account — typically following a successful Modulr collection and subsequent sweep. Upon receipt:

  • The holding account balance record is updated.
  • A hold-period timer is initiated via Inngest.
  • The clawback reserve requirement is evaluated.

Payment Sent

Fired when an outbound payment from the Griffin holding account to an agent's client account is confirmed. Upon receipt:

  • The forwarding record is marked complete.
  • The holding account balance is decremented.
  • Any downstream reconciliation events are dispatched.

Signature Validation

Griffin webhook payloads are verified using Griffin's signing mechanism before any state changes are made. Invalid signatures result in a 401 Unauthorized response.


Idempotency

Both handlers are fully idempotent. Each webhook event carries a unique identifier that is checked against previously processed events before any action is taken. Re-delivered events (e.g. due to provider retries) are safely ignored without causing duplicate records, double-triggered jobs, or inconsistent balance state.


Downstream Event Flow

After updating database records, each handler dispatches one or more Inngest events to continue the relevant workflow asynchronously:

Modulr collection.paid
  → DB: mark collection as paid
  → Inngest: trigger sweep-to-holding job

Modulr collection.failed / returned
  → DB: update collection status
  → Inngest: trigger alert + reserve re-evaluation

Modulr mandate.auddis_accepted / rejected
  → DB: update mandate status
  → Inngest: notify consuming application (e.g. agentOS gatekeeping)

Griffin payment_received
  → DB: update holding account balance
  → Inngest: start hold-period timer

Griffin payment_sent
  → DB: mark forwarding as complete
  → Inngest: trigger reconciliation

Security Notes

  • Webhook endpoints are public but not authenticated via the standard API key mechanism — they are secured exclusively through provider-side payload signing.
  • Never expose raw webhook payloads in logs. Both handlers should be treated as an ingress boundary and only trusted after signature verification passes.
  • Both endpoints return 200 OK promptly to acknowledge receipt; all processing happens asynchronously via Inngest to avoid provider-side timeout retries.