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:

  1. Expose an endpoint where seQura can POST notifications.
  2. 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

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:

  1. Send order data to seQura for verification.
  2. Mark the order as completed or waiting for review in your database.
  3. Send the order reference to seQura (if not already sent).
  4. Respond to the IPN with a 200 OK status.

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_1 at checkout start, seQura checks uniqueness and responds with 409 Conflict if it's not unique.
  • During step 3, when updating the confirmed order with the reference. Again, seQura responds with 409 Conflict if 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:

  1. There's a sync delay between your storefront and backend.
  2. 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:

  1. seQura POSTs to notify_url.
    • You PUT confirmation to seQura (without order number).
    • seQura responds with 200.
    • You create the order from the cart.
  2. You respond with 307 and a URL.
  3. seQura POSTs to that URL.
    • You PUT confirmation to seQura with the order number.
    • seQura responds with 200.
  4. You respond with 200.

Notes:

  • The IPN accepts up to 2 redirects (max 3 POST requests).
  • The Location: URL can be the same as a previous URL, including notify_url.
  • 302 Found currently works but is deprecated for new integrations. 302 typically 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.179
  • 34.252.147.155
  • 52.211.243.177

Remember: you won't have access to the session when receiving the IPN. If you need session data, include it in notification_parameters.

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 3000

Ngrok 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.