3. Put the order on hold and confirm it
Once the shopper provides enough information and we're ready to proceed, two things can happen:
- The order is approved and ready for fulfillment. Your shop must confirm the order is being placed. This is the most common scenario.
- The order needs review and is put on hold. Your shop must acknowledge the order but mark it as not ready for shipment. Once approved, confirm the order to proceed with fulfillment.
This step serves two purposes:
- Ensure the cart hasn't changed during checkout. If it has, restart the process.
- Help your logistics: confirmed orders can ship immediately, while on hold orders wait for approval.
We work to keep the on hold period as short as possible.
For the shop to know about on hold orders that get rejected, see the Webhooks API.
Overview
seQura notifies your shop about order approval or review status via an IPN (Instant Payment Notification) callback to the URL you provided in the first API call.
To implement IPN:
- Expose an endpoint where seQura can
POSTnotifications. - When you receive a request, update the order via seQura's API (place on hold or confirm) before responding with a success status code.
Here's the interaction when an order is approved directly:
%%{init: {
"theme": "base",
"themeVariables": {
"background": "#F0F0F0"
}
}}%%
sequenceDiagram
participant Shop
participant seQura
seQura->>+Shop: IPN request (approved)
activate seQura
Shop->>+seQura: Confirm order
seQura-->>-Shop: Order update response
Shop-->>-seQura: IPN response
deactivate seQura
Or like this when the order goes first through review:
sequenceDiagram
participant Shop
participant seQura
seQura->>+Shop: IPN request (needs review)\
activate seQura
Shop->>+seQura: Place order on hold\
seQura-->>-Shop: Order update response
Shop-->>-seQura: IPN response\
deactivate seQura
seQura->>+Shop: IPN request (approved)\
activate seQura
Shop->>+seQura: Confirm order\
seQura-->>-Shop: Order update response
Shop-->>-seQura: IPN response\
deactivate seQura
Authorize & Capture (optional)
Merchants who have Authorize & Capture enabled in their contract can split the “approved” step into two distinct decisions:
- Authorize — acknowledge the approved order and close the checkout form for the shopper, without yet committing to capture the payment. The shopper is redirected to return_url immediately, just as on confirmed.
- Capture (later) — confirm the order, dispatch it for fulfilment, and run the down-payment-on-confirmation charge as usual. Or, alternatively, void the authorization and release the reservation without producing a refund.
This matches the Authorize & Capture model commonly offered by PSPs for credit-card payments and is intended for flows in which the merchant cannot decide synchronously (travel, high-ticket, marketplace). It is a per-merchant opt-in and is off by default.
Eligibility
- The merchant’s account must have Authorize & Capture enabled. Without the flag, the API returns
409 Conflictto anystate=authorizedrequest. - The order’s product_code must not be
i1. Thei1product is captured immediately on confirmation and has no authorization step to delay;i1orders return409 Conflictif the shop tries to authorize them and must keep usingapproved → confirmed.
Authorize
When the IPN includes sq_state=approved and the merchant wants to close the form without committing to capture yet, the shop sends a PUT to the order URL with state="authorized" instead of state="confirmed".
- The checkout form closes and redirects to return_url, exactly as on confirmed.
- No IPN is emitted when the order enters authorized — the shop drove the transition itself.
- The order is not dispatched for fulfilment yet. The down-payment-on-confirmation charge is not run yet.
- SeQura starts a per-merchant authorization window timer (default 24 hours, configurable up to 6 days / 144 hours). If the shop has not captured or voided by the time the window expires, SeQura automatically voids the authorization (see below).
Capture
To capture (i.e. confirm) an authorized order, send a PUT with state="confirmed" from the authorized state. This runs the standard confirmation flow:
- The order is dispatched for fulfilment.
- The down-payment-on-confirmation charge is run, if applicable to the product.
- Subsequent IPNs and webhooks behave exactly as for any other confirmation.
Void
To void an authorized order — releasing the shopper’s reservation without ever placing a charge on their statement — send a PUT with state="cancelled" from the authorized state.
- No refund is produced. Voiding moves the order directly to the terminal cancelled state, not through the refund pipeline. This avoids the shopper-visible “charge then refund” pair that a regular cancellation would generate.
- The reservation on the shopper’s account is released.
- No further capture is possible after void; the order is terminal.
state="cancelled" is only accepted from authorized. From other states the regular cancellation/refund endpoints continue to apply.
Auto-void after window expiry
If the shop neither captures nor voids before the configured authorization window elapses, SeQura voids the authorization automatically with the same semantics as a merchant-driven void (no refund, terminal cancelled). The default window is 24 hours; the per-merchant maximum is 6 days (144 hours).
Configuration
To use the IPN workflow, include at least the notify_url field in the merchant section of your initial API call. We recommend also including a return_url for redirecting shoppers after checkout.
The Notify URL: Include notify_url in the merchant section. seQura sends a POST request to this URL to trigger confirmation or on hold processes.
When you receive a request, find the order in your database. seQura includes your order reference (if known), seQura's order reference, and the order state (see IPN Request Example below). If these aren't enough to identify the order, include additional parameters in the URL or the optional notification_parameters structure.
For shared shop platforms, we recommend including a digital signature in notification_parameters to prevent fake requests. See Securing the IPN call.
The Return URL: Include return_url in the merchant section. seQura redirects the shopper here (via GET) after confirmation or on hold. This is typically your order confirmation page.
If the URL contains SQ_PRODUCT_CODE, seQura replaces it with the product code. For example, if the shopper uses invoicing and return_url is http://shop.example.com/checkout/confirmed?payment_method=sq-SQ_PRODUCT_CODE, they'll be redirected to http://shop.example.com/checkout/confirmed?payment_method=sq-i1. This lets you show different messages based on the payment product used.
Processing the IPN
When seQura sends the IPN, it means seQura is ready to guarantee payment for the order. You can proceed with placing the order.
If the order can proceed to fulfillment, the IPN includes sq_state=approved. Finalize the order with seQura as the payment method.
If the order needs manual review, the IPN includes sq_state=needs_review. Place the order on hold—the order is finalized with seQura but not ready for fulfillment yet. Once approved, you'll receive another IPN with sq_state=approved.
There are several variations to this workflow, depending on whether your shop can fully process the IPN. The sections below describe each case:
Handling an IPN completely
To fully handle an IPN:
- Send order data to seQura for verification.
- Mark the order as completed or waiting for review in your database.
- Send the order reference to seQura (if not already sent).
- Respond to the IPN with a
200 OKstatus.
In step 1, make a PUT request to the URL from the initial solicitation's Location header. Include all order data plus state="confirmed" or state="on_hold".
If the IPN includes sq_state="needs_review": place the order on hold in your system and send state="on_hold" to seQura.
If the IPN includes sq_state="approved": confirm the order in your system and send state="confirmed" to seQura.
seQura usually responds with 200 OK, so proceed with steps 2-4. However, if the cart, delivery address, or other details changed unacceptably, seQura responds with 409 Conflict and a JSON body explaining the issues. In this case, don't complete the order or send the order reference, but still respond to the IPN with 200 OK.
After handling the first IPN (when seQura receives 200 OK), the shopper is redirected to return_url regardless of whether the order update succeeded. Your return_url handler must check the order status before deciding what to display, since the order might be on hold or ready for fulfillment.
Problem: Order reference missing
seQura can't process an order or pay you until you provide order_ref_1. We follow up weekly on confirmed orders missing this reference. Recurring issues may lead to service disconnection.
Problem: Order reference not unique
seQura requires (merchant.id, merchant_reference.order_ref_1) to be unique for confirmed orders. Duplicate references won't be processed. This error can occur in two places:
- During step 1, when confirming the order. If you provided
order_ref_1at checkout start, seQura checks uniqueness and responds with409 Conflictif it's not unique. - During step 3, when updating the confirmed order with the reference. Again, seQura responds with
409 Conflictif not unique. This case is more complex: the order is confirmed with seQura as payment method, but seQura can't process it further.
Order should not be paid with seQura (410)
Between checkout start and the IPN, the cart might change in ways that prevent order completion:
- The shopper completed the order via another payment method in a different tab.
- An item is no longer available (or not at the expected price).
In these cases, don't confirm the order with seQura. Respond to the IPN with 410 Gone. This tells seQura the approved credit won't be used and any down payment should be refunded.
After receiving 410 Gone, seQura redirects the shopper to return_url.
Order cannot be found (404)
If you can't find the order using the notify_url data or request parameters, respond with 404 Not Found. seQura assumes either:
- There's a sync delay between your storefront and backend.
- The shopper stayed too long in checkout and the unconfirmed order was deleted.
seQura retries the IPN a few times for sync issues. If the 404 persists, seQura treats it as a 410.
Order already confirmed with seQura (409)
Due to communication or sync errors, your shop might consider the order confirmed while seQura's IPN service sees it as needing confirmation. Respond with 409 Conflict to signal seQura to investigate.
After receiving 409 Conflict, seQura redirects the shopper to an error page.
Temporary server problem (5xx)
If you encounter temporary server issues during IPN processing (like database unavailability), respond with a 5xx status. seQura retries for up to 24 hours and won't cancel the order or refund the first installment while you respond with 5xx.
Multi-request notification (30x)
If you respond with 307 Temporary Redirect and a Location: header, seQura makes another POST to the returned URL. This works around technical limitations in platforms like PrestaShop. The sequence becomes:
- seQura
POSTs tonotify_url.- You
PUTconfirmation to seQura (without order number). - seQura responds with
200. - You create the order from the cart.
- You
- You respond with
307and a URL. - seQura
POSTs to that URL.- You
PUTconfirmation to seQura with the order number. - seQura responds with
200.
- You
- You respond with
200.
Notes:
- The IPN accepts up to 2 redirects (max 3
POSTrequests). - The
Location:URL can be the same as a previous URL, includingnotify_url. 302 Foundcurrently works but is deprecated for new integrations.302typically signals "GET this URL", which can cause hard-to-track bugs.- Other 30x codes aren't accepted and cause IPN failure.
IPN request examples
seQura includes order references in the IPN request. Assuming your original API request contained:
{
"order": {
"merchant": {
"id": "...",
"notify_url": "http://shop.example.com/ipn-me",
"return_url": "http://shop.example.com/checkout/confirmed?payment_method=sq-SQ_PRODUCT_CODE",
},
"merchant_reference": {"order_ref_1": "MHPULMKOE"},
...And seQura returned a URL ending in /9201b602-94b3-4804-8ef2-080c518378ee in the Location header, the IPN request looks like this:
POST /ipn-me HTTP/1.1
User-Agent: seQura-IPN/1.0
Connection: close
Content-Type: application/x-www-form-urlencoded
Content-Length: 164
Host: shop.example.com
order_ref=9201b602-94b3-4804-8ef2-080c518378ee&order_ref_1=MHPULMKOE&product_code=pp3&sq_state=approved&approved_since=0
If the order needs to be put on hold:
POST /ipn-me HTTP?1.1
User-Agent: seQura-IPN/1.0
Connection: close
Content-Type: application/x-www-form-urlencoded
Content-Length: 172
Host: shop.example.com
order_ref=9201b602-94b3-4804-8ef2-080c518378ee&order_ref_1=MHPULMKOE&product_code=pp3&sq_state=needs_review&needs_review_since=0
approved_since: Seconds since seQura approved the order. Useful for debugging when you return 5xx errors. We recommend logging this value. Only present for approved orders.
needs_review_since: Seconds since seQura requested the order be put on hold. Useful for debugging 5xx cases. We recommend logging this value. Only present for orders needing review.
product_code: Used by our Magento and PrestaShop plugins. Other integrators can ignore it.
Securing the IPN call
Include a secure token—a short string that's hard to guess, easy to verify, and used only once.
Creating a secure token: Use a cryptographic hash function with a secret salt (a string only your application knows). In this example, the token is the SHA1 digest of 1234:sUpErSeCrEtSaLt (cart ID + colon + salt).
{
"order": {
"merchant": {
"notify_url": "https://my.shop.tld/checkout/sequra-ipn",
"notification_parameters": {
"cart": "1234",
"token": "4207e9302d31d4fa2dbcaf9dfb45249d2581b9f8"
},IPs used in the IPN request
seQura uses 3 static IPs for both sandbox and production:
34.253.159.17934.252.147.15552.211.243.177
Tips for development environments
Using tunnels
If you're behind a firewall, our servers can't reach your notify_url unless you expose it. We recommend ngrok to expose a specific port.
For example, expose port 3000 with:
$ ngrok http 3000Ngrok generates a unique URL for your port. For example, if ngrok gives you http://12345678.ngrok.io, your notify_url would be http://12345678.ngrok.io/checkout/sequra-ipn.
Missing SSL certificate
The IPN requires HTTPS. If your server doesn't have a valid SSL certificate, the IPN won't work.
In sandbox, you can bypass this by prefixing the URL with unverified-https://. For example: unverified-https://my.shop.tld/checkout/sequra-ipn/8765432
Note: This doesn't work in production.
Testing the on hold flow
See the FAQ for options to test what happens when an order is put on hold.
Updated 19 days ago