Skip to main content
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

How it works

  1. Each morning at 7:30 a.m. ET, Rightfoot starts checking the balances of your enrolled borrowers.
  2. 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.
  3. You run the ACH for each entry, for amount_cents, on the debit_by date. Store payment_reference with the payment in your system. It does not need to go on the ACH entry itself.
  4. You report each outcome with Report Payment Results, keyed on payment_reference: settled, returned with its R-code and return date, or not_attempted if 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 a Rightfoot-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:
  1. Split the header on , and read t and v1.
  2. Compute the HMAC over <t>.<raw body>, using the body exactly as received, before any JSON parsing.
  3. Compare it to v1 with a constant-time comparison.
  4. Reject the request if t is more than a few minutes old, so a captured request cannot be replayed.
Python

Responding and retries

Respond with any 2xx 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.
Delivery is at least once. You can receive the same batch_id more than once, so check whether you have already processed it before running any debits.

Reporting outcomes

Until you report an outcome for a payment_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 with credentials: {"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

Rightfoot-Signature
string
required

t=<unix seconds>,v1=<hex HMAC-SHA256 of "<t>.<raw body>", keyed with your signing_secret>

Body

application/json
type
enum<string>
Available options:
payment_notifications.batch
batch_id
string<uuid>

The same on every delivery attempt. Use it to ignore a batch already processed.

created_at
string<date-time>
notifications
object[]

One entry per debit to run. Empty on a day nobody cleared.