Webhooks
Payment Notifications
The daily list of borrowers whose balance cleared, for lenders who run the ACH themselves
WEBHOOK
Payment Notifications Webhook
If you run the ACH yourself, Rightfoot tells you who to debit. Every morning it checks your enrolled borrowers’ balances, and sends one signed batch to your webhook listing the borrowers whose balance covers the payment. You debit them through your own setup, then report the outcomes.Before you start
- Register your webhook URL as your default ACH key, and store the
signing_secretfrom the response. It is shown only once. - Enroll borrowers. Your collection policy and any
policy_overridesdecide when a balance is high enough. - If your endpoint restricts inbound traffic by IP, allowlist Rightfoot’s IPs.
How it works
- Each morning at 7:30 a.m. ET, Rightfoot starts checking the balances of your enrolled borrowers.
- Once those checks finish, it sends one batch for the day. Every borrower whose balance cleared is in it, with the amount to debit and the balance it saw.
- You run the ACH for each entry, for
amount_cents, on thedebit_bydate. Storepayment_referencewith the payment in your system. It does not need to go on the ACH entry itself. - You report each outcome with Report Payment Results, keyed on
payment_reference:settled,returnedwith its R-code and return date, ornot_attemptedif you did not run it.
A batch is sent every day, even when nobody cleared. An empty
notifications list means a quiet day. No batch at all means something is wrong.Payload
Verifying the signature
Each request carries aRightfoot-Signature header:
t is the Unix time the request was sent. v1 is the hex HMAC-SHA256, keyed with your signing_secret, of t, a period, and the raw request body. To verify a request:
- Split the header on
,and readtandv1. - Compute the HMAC over
<t>.<raw body>, using the body exactly as received, before any JSON parsing. - Compare it to
v1with a constant-time comparison. - Reject the request if
tis more than a few minutes old, so a captured request cannot be replayed.
Python
Responding and retries
Respond with any2xx status once you have stored the batch. Rightfoot does not follow redirects, and waits up to 30 seconds for a response.
Anything else, a timeout included, is retried with backoff for about two hours. A batch still undelivered after that is held and sent again the next morning, under the same batch_id, before that day’s batch. Every attempt is signed again with a fresh t; the body is the same each time.
Reporting outcomes
Until you report an outcome for apayment_reference, Rightfoot treats that debit as in flight and does not notify you about that borrower again. Report every debit in the batch, including the ones you did not run (not_attempted).
Upload results at least once a day. Each upload, even one with only the header row, tells Rightfoot your results are current. If no upload arrives for 36 hours, Rightfoot stops notifying you of new debits until one does.
Rotating the secret or changing the URL
To change the URL or rotate the secret, replace the key’s credentials withcredentials: {"url": "..."}. The response carries a new signing_secret, and every request from then on is signed with it. The previous secret stops being used immediately, so update your endpoint as soon as you have the new one.Headers
t=<unix seconds>,v1=<hex HMAC-SHA256 of "<t>.<raw body>", keyed with your signing_secret>
