Register your endpoint
In the dashboard, open Webhooks and add your HTTPS endpoint. Copy the signing secret from the confirmation: it is shown once and cannot be recovered afterwards. Ringup then delivers every event below to it, signed. You can register more than one endpoint, disable or delete one at any time, and each environment (Test and Live) keeps its own list. The same page shows each endpoint’s recent deliveries, with attempt counts and the last error when one failed. Prefer to script it? The API does the same thing, with your environment’s key:The envelope
Every event has the same shape:Event catalog
The catalog is deliberately small. A first-time link payment is a
checkout.succeeded like any
other, not a separate event.
checkout.succeeded
The one you build against. Its data carries everything you need to mark an order paid:
order_id you passed (or platform_call_id), store the charge_id, and flip your
order to paid.
A payment made with Apple Pay or Google Pay on the pay page arrives as this same event with
wallet naming the wallet and card null: a wallet payment saves no card, so there is no brand
or last four to report. Label it “Apple Pay” or “Google Pay” in your own surfaces rather than
treating the missing card as a gap.
checkout.failed
It fires on a decline as well as an expiry. A caller whose card is declined and who then hangs
up is the case your server most needs to hear about, so it is an event, not something you discover
by polling.
reason tells the two cases apart:
declined. A card was charged and the issuer said no.charge_idnames the attempt, andlast_payment_errorsays why.expired. The session lapsed unpaid.charge_idandlast_payment_errorarenull: nothing was attempted, so there is no error to report.
last_payment_error is the same error object the 402 returned, so the parser you already
wrote for a synchronous decline handles the asynchronous one unchanged. See
Errors for every field. It omits request_id: that identifies a request,
and an event is not one.
checkout.step_up_required
Ringup screens the caller’s number on every checkout. When it finds a positive risk signal, the
caller’s saved card is not offered on that call: they are texted a payment link instead, which
proves possession of the phone. This event tells you that happened, so the answer to “why did my
caller get a link when they have a card on file” is in your logs before they ask.
It fires once per session, whichever signal found the risk, and only on a real signal. A
screening lookup that errors or cannot run is treated as neutral and produces no event, because a
gap on our side is not a fact about your caller.
reasons carries stable codes, not prose: ported_recently when the number changed hands inside
the last seven days, attestation_C or attestation_F when the carrier’s signature on the
original call was poor or failed.
Nothing here is spoken to the caller, and your agent should not repeat it. The payment line already
handles the moment gracefully: it offers the link warmly and never mentions checks or verification.
Charge statuses
A charge is in one of three states; the same values appear on the session and in the charge response:succeeded: the charge settled. This is the only status that means money moved.pending: not settled. The processor has not confirmed an outcome, and the payment may or may not have gone through, so never announce it either way.failed: the charge was declined or errored; nothing was charged.
Getting it right
Three rules cover almost every webhook bug:- Verify the signature. Each request carries a
Ringup-Signatureheader, an HMAC of the raw body plus theRingup-Timestamp. Recompute it with your endpoint’s signing secret and reject a mismatch or an old timestamp, so nobody can forge an event. - Dedupe on
event_id. Delivery is at-least-once: Ringup retries on any non-2xx response, so an event can arrive more than once. Treat a repeatedevent_idas a no-op. - Acknowledge fast. Return
2xximmediately and do your work asynchronously. Ringup retries with backoff and parks a persistently failing endpoint after several attempts.
Signature scheme.
Ringup-Signature is an HMAC-SHA256 over the timestamp and the raw request
body, signed with your endpoint’s secret, sent as v1=<signature>. The secret is returned once,
in the registration response.Next steps
Testing
Trigger real events in test mode and watch them arrive.
API reference
Every field of every endpoint, with a live playground.