Skip to main content
One of the great features of Loop’s integration with Stripe is that in most cases you can continue to use Stripe’s webhooks for any automations you have. Since Loop updates the Customer and Invoice record automatically, Stripe webhooks continue to fire.

Stripe webhooks

When an invoice’s payment status in Stripe changes to paid, the invoice.paid event in Stripe will be emitted. We suggest you also listen to the payment.intent_succeeded to ensure you are notified of a payment.

Common confusion

When a Loop payment occurs, a payment_intent.canceled event is emitted. This is because Stripe will want to charge the payment method on file (fiat). Thus, Loop cancels this event and instead updates the invoice to be paid outside of Stripe."The invoice.paid event will emit once the payment takes place on chain and Loop marks the invoice as paid. There is nothing you need to do here but be aware of this. If you have Stripe already configured, you may also already be listening to the invoice.charge.succeeded event from Stripe. This invoice.charge.succeeded event is triggered specifically when a single charge associated with an invoice successfully completes, while an invoice.paid event is triggered whenever an entire invoice is marked as paid, which can include scenarios where the payment was manually marked as paid outside of a standard charge process (which is the case when you use Loop!). As a result, it is important to ensure you are listening to invoice.paid.

Loop webhooks

If you would like, you can still listen to webhook events emitted from Loop. When running testing, some teams like to listen to Loop webhooks in Slack. If you would like to configure Loop’s webhooks, you can set them up using the Webhooks endpoint under the Stripe integration section.

Available webhooks

WebhookDescription
AgreementSignedUpTriggered when a new customer completes checkout
TransferCreatedTriggered when a draft invoice is created
TransferFinalizedTriggered when a draft invoice is finalized
TransferProcessedTriggered when a payment confirms onchain
LatePaymentTriggered 10 minutes after a new customer completes checkout
ScheduledAgreementCancelTriggered when a subscription is canceled and the cancelation date is in the future
AgreementCancelledTriggered when a subscription is canceled

Webhook retry logic

Loop has a standard retry cadence if a webhook is not successfully ingested. Loop will retry 3 times immediately and then start to back off over the next ~20 seconds. There are about 15 retries within this period. After that, if Loop still receives a failure message from your endpoint, retries are attempted every 20 seconds.

Demo App

See https://github.com/LoopCrypto/loop-demo-app for an example of how to integrate with our webhook and perform actions accordingly using the Loop SDK.

handler.js

handler.js is the main entry point of the app, which will validate the webhook, do some basic error checks, and handles the webhook based on the different webhook types.

signup.js

signup.js handles the AgreementSignedUp webhook. The example code will send out the initial transfer request, plus 5 subsequent transfer requests based on the item’s frequency configuration.

transfer-processed.js

transfer-processed.js handles the TransferProcessed webhook. The example will log the transfer if it is successful, and do one retry request if the transfer failed.
I