Webhooks are the implemented integration surface for API-related events in Repejo today. When a matching event is published, a delivery is created and sent to each active webhook endpoint.
Current state: Webhook endpoints are configured in the Repejo interface and receive signed JSON payloads. A response is considered successful when the endpoint returns HTTP 2xx.
type EventType =
| "payer.created"
| "payer.updated"
| "subscription.created"
| "subscription.updated"
| "transaction.created"
| "transaction.updated"
| "receivable.created"
| "receivable.updated"
| "payment_session.created"
| "payment_session.succeeded"
| "payment_session.cancelled";
The payment_session.*
family is emitted for
Payment Sessions
("Pay by Link"); the other families cover the underlying
donor/mandate/charge lifecycle.
A single completed Payment Session emits events from both families, in this order:
payment_session.created // session created (donor not yet finished)
payment_session.succeeded // recurring mandate signed
subscription.created // the resulting subscription/mandate (data.id = sub_…)
Treat
payment_session.succeeded
as the authoritative reconciliation event for a Payment Session — it
carries the metadata
you sent on POST /payment_session.
Subscribe to whichever family matches your use case (or both), and
deduplicate on X-Repejo-Event-ID.
type WebhookPayload = {
sent_at: string;
event_type: EventType;
data: Payer | Subscription | Receivable | Transaction | PaymentSession;
};
Type note:
amount
is delivered as a string
(e.g. "150"), not a
number, in both
payment_session.*
and subscription.*
payloads. Parse it accordingly.
subscription.created.data.method
for an Autogiro mandate contains personal data:
personal_identity_number
(Swedish personnummer), clearing_number,
account_number
and payer_number.
Treat webhook payloads as sensitive: always verify the signature before parsing, store and transmit the payload securely, and restrict access to the personal data it carries.
payer
when the association has been preloaded.
payment_method
as a nested object with type-specific fields (see PaymentMethod).
The field is null
when no payment method is linked.
payer
as a nested object (same fields as the subscription payer). The field
is null
when no payer is linked or the payer can no longer be loaded (for
example, it was deleted).
external_transaction_id.
It holds the external id when the receivable has a successful transaction with
one, and is null otherwise.
Content-Type: application/json
User-Agent: Repejo-Webhooks/1.0
X-Repejo-Delivery-ID: <delivery_id>
X-Repejo-Event-ID: <event_id>
X-Repejo-Event-Type: <event_type>
X-Repejo-Attempt: <attempt>
Repejo-Signature: sha256=<hex>
Repejo-Signature
is generated with HMAC-SHA256 over the raw JSON payload and the secret key created for the endpoint.
The signature is sent in the format sha256=<hex>.
Always compare against the raw body, not re-serialized JSON.
Failed deliveries are retried with exponential backoff via Oban. The current configuration performs up to 20 attempts, which spans up to roughly twelve days in total.
If all attempts fail, the delivery is marked as abandoned.
This flow is intended for organisations that use Repejo to collect and sign the Autogiro mandate, but keep the Bankgirocentralen connection and recurring charge management in their own CRM or backend.
Typical examples are face-to-face fundraising and website checkouts where Repejo handles the donor experience, while your system owns the downstream Autogiro setup.
Create an HTTPS endpoint in your system that accepts POST requests with a raw JSON
body. Verify the
Repejo-Signature
header against the raw body before parsing the payload.
Return a 2xx response only after the event has been accepted for processing. Non-2xx responses are retried automatically.
In Repejo, create a webhook endpoint that points to your URL and subscribe it to
both subscription.created
and subscription.updated.
You need both events because a mandate can be created first and then updated as the subscription changes.
Your endpoint may receive subscription events for payment methods other than autogiro_external.
Always inspect
payload.data.payment_method_type
and ignore events that are not relevant to your integration.
The same subscription can be delivered multiple times. This can happen because the subscription is updated more than once, and because failed webhook deliveries are retried. Treat the handler as idempotent.
X-Repejo-Event-ID
to deduplicate retries of the same event.
data.id as the
stable subscription identifier in your CRM.
subscription.updated
deliveries do not create duplicate mandates or payment instructions.
If you need to link the subscription to an external campaign or source in your CRM, define custom attributes in Repejo and send them through the checkout.
A common pattern is to include a campaign identifier that maps to a Salesforce campaign or another CRM entity.
These values are included in the
metadata
property on the subscription payload, so your webhook consumer can use
payload.data.metadata
when creating or updating the record in your CRM.
In test, all payment methods are faked, which makes end-to-end testing of this integration straightforward.
Start by setting up a faked payment method in your test environment, then create a checkout that uses it and complete the subscription flow.
Confirm that your endpoint receives
subscription.created
and, when applicable,
subscription.updated
with the expected
payment_method_type
and metadata
values.