Webhooks

To get subscription status updates, your POS can receive events through a webhook URL shared with seQura.

Supported event types

Event typeWhen it fires
subscriptions/createdSubscription created and confirmed by client
subscriptions/activatedAll subscription items have been activated
subscriptions/cancelledSubscription cancelled
subscriptions/payment_status_changedPayment succeeded or failed
subscriptions/instalment_date_changedMonthly charge day changed
subscriptions/renting_plan_changedPayment plan modified
subscriptions/customer_updatedCustomer personal data updated
subscriptions/payment_method_updatedPayment method changed
subscriptions/payment_successPayment completed successfully
subscriptions/payment_errorPayment failed to complete
aml_documentation_requiredAML check requires customer documents
aml_documentation_validatedAML documentation approved
order/account_in_debtPart payment order is in debt
order/account_up_to_datePart payment order balance is up to date
needs_cardCustomer must confirm / update payment card
deniedFired when seQura's risk engine rejects the checkout application.
cancelledFired when a checkout is cancelled before confirmation — by the operator, the customer, or a system timeout

Webhook Delivery Behaviour

Request format

  • Method: POST
  • Content-Type: application/x-www-form-urlencoded
  • User-Agent: SeQura-Event/1.0 (www.sequra.es)
  • Timeout: 5 seconds per attempt

Expected response

The endpoint must return a 2xx status code to acknowledge receipt. No specific response body is required.

Return 501 to signal that a particular event type is not supported — SeQura will treat this as a successful delivery and will not retry.

Any other non-2xx status (4xx, 5xx) is treated as a failure and triggers a retry.

Redirects

SeQura follows up to 4 redirects (301, 302, 307, 308). Absolute and relative Location headers are both supported. Exceeding 4 hops causes the delivery to fail and retry.

Retries

Failed deliveries (non-2xx response, timeout, or connection error) are retried up to 10 times with exponential backoff.

After 10 exhausted retries the event is permanently dropped.

Delivery guarantees

  • At-least-once — the same event may be delivered more than once (e.g. after a retry following a timeout where the endpoint had already processed the request). Processors should be idempotent: use event_id as a deduplication key.
  • Events are delivered asynchronously — there is no guaranteed ordering between different event types for the same order.

Signature Verification

Every webhook delivery includes an X-SeQura-Signature header containing an HMAC-SHA256 signature of the raw request body, hex-encoded. Verify it to confirm the payload genuinely came from seQura and has not been tampered with.

📘

HTTP header names are case-insensitive

Per the HTTP specification (RFC 9110), header field names are case-insensitive. seQura may send this header as X-SeQura-Signature, x-sequra-signature, or any other casing (for example, header names are lowercased over HTTP/2), so read it case-insensitively. Most frameworks normalize header names for you—e.g. PHP exposes it as $_SERVER['HTTP_X_SEQURA_SIGNATURE'].

Retrieve your signature_secret from GET /merchants/:merchant_ref/credentials Please note that this an endpoint on different domain (main checkout API)

expected = OpenSSL::HMAC.hexdigest("SHA256", signature_secret, request.raw_post)
ActiveSupport::SecurityUtils.secure_compare(expected, request.headers["X-SeQura-Signature"])
import hmac
import hashlib

expected = hmac.new(secret.encode(), body, hashlib.sha256).hexdigest()
hmac.compare_digest(expected, request.headers.get("X-SeQura-Signature", ""))
$expected = hash_hmac('sha256', $rawBody, $secret);
hash_equals($expected, $_SERVER['HTTP_X_SEQURA_SIGNATURE'] ?? '');

Always use a constant-time comparison function (secure_compare, compare_digest, hash_equals) to prevent timing attacks.

Common attributes

AttributeDescription
charsetUTF-8
utf√ - control character to check encoding is correct.
eventevent type
event_idunique event id
order_refUUID of subscription (generated by SeQura)
order_ref_1Subscription reference number provided by merchant
order_ref_2Optional second reference number

Payload samples

subscriptions/created

Sent when subscription is fully confirmed by client. Includes masked payment method, contract number, confirmation time

{
  "charset": "UTF-8",
  "utf": "√",
  "order_ref_1": "990093571",
  "order_ref_2": null,
  "order_ref": "3e88b4a9-58d6-4fcb-b347-52189e9c3952",
  "event": "subscriptions/created",
  "event_id": "b9008195-8747-4697-9bda-ac19d56bb2c6",
  "credit_card": "************2160",
  "credit_card_type": "VISA",
  "bank_account_last_digits": null,
  "contract_number": "A681875191",
  "confirmed_at": "2026-02-16T11:44:28.000+01:00"
}

subscriptions/activated

Sent when subscription is activated (either all product delivered, or 30 days passed and subscription was activated automatically)

 {
   "charset": "UTF-8",
   "utf": "√",
   "order_ref_1": "990093571",
   "order_ref_2": null,
   "order_ref": "3e88b4a9-58d6-4fcb-b347-52189e9c3952",
   "event": "subscriptions/activated",
   "event_id": "f2d641e7-9f46-41bd-875d-d45248c1d089",
   "activated_at": "2026-02-16T11:44:28.000+01:00"
 }

subscriptions/cancelled

Sent when subscription is cancelled

{ 
  "charset": "UTF-8",
  "utf": "√",
  "event": "subscriptions/cancelled",
  "event_id": "1234",
  "order_ref_1": "pos_1234",
  "order_ref_2": "",
  "order_ref": "060eef19-da6c-4a5b-9a43-8bf43cb63a2e",
  "updated_at": "2025-07-03 12:26:24.093525003 CEST +02:00"
 }

subscriptions/updated

Sent when subscription is updated (cart changed on product exchanges)

{
   "charset": "UTF-8",
   "utf": "√",
   "order_ref_1": "990093571",
   "order_ref_2": null,
   "order_ref": "3e88b4a9-58d6-4fcb-b347-52189e9c3952",
   "event": "subscriptions/updated",
   "event_id": "3d201e87-e6ab-445d-8283-32a4f85c7138",
   "updated_at": "2026-02-16T11:44:34.146+01:00"
 }


subscriptions/instalment_date_changed

Sent when the monthly charge date is changed by seQura (by customer's request).

{
   "charset": "UTF-8",
   "utf": "√",
   "order_ref_1": "990093571",
   "order_ref_2": null,
   "order_ref": "3e88b4a9-58d6-4fcb-b347-52189e9c3952",
   "event": "subscriptions/instalment_date_changed",
   "event_id": "3b533849-1085-48c0-a767-14123a8da3b1",
   "old_instalment_day": 5,
   "new_instalment_day": 15,
   "changed_on": "2026-04-02"
}
FieldDescription
old_instalment_dayPrevious day of month for charges (1–28)
new_instalment_dayNew day of month for charges (1–28)
changed_onDate the change takes effect (ISO 8601)

subscriptions/renting_plan_changed

Sent when the subscription payment plan is modified.

 {
   "charset": "UTF-8",
   "utf": "√",
   "order_ref_1": "990093571",
   "order_ref_2": null,
   "order_ref": "3e88b4a9-58d6-4fcb-b347-52189e9c3952",
   "event": "subscriptions/renting_plan_changed",
   "event_id": "d22cb7d1-7c3c-4960-a58e-732d1c575be0",
   "next_charge_date": "2026-05-02",
   "oldest_overdue_charge_date": null,
   "current_order_value": "515.28"
 }
FieldDescription
next_charge_dateDate of the next scheduled charge (ISO 8601)
oldest_overdue_charge_dateEarliest unpaid charge date, if any (ISO 8601)
current_order_valueCurrent outstanding order value

subscriptions/customer_updated

Sent when the customer's personal data has been updated in seQura.

{
  "charset": "UTF-8",
  "utf": "√",
  "event": "subscriptions/customer_updated",
  "event_id": "1234",
  "order_ref_1": "pos_1234",
  "order_ref_2": "",
  "order_ref": "060eef19-da6c-4a5b-9a43-8bf43cb63a2e",
  "given_names": "María",
  "surnames": "García López",
  "email": "[email protected]",
  "phone": "+34666123456",
  "date_of_birth": "1990-01-01",
  "nin": "12345678A"
}

All data fields are optional. Only updated fields are included.

subscriptions/payment_method_updated

Sent when the customer's payment method changes.

{
   "charset": "UTF-8",
   "utf": "√",
   "order_ref_1": "990093571",
   "order_ref_2": null,
   "order_ref": "3e88b4a9-58d6-4fcb-b347-52189e9c3952",
   "event": "subscriptions/payment_method_updated",
   "event_id": "5264d1fe-479d-4843-804d-51bdcf8d0d34",
   "credit_card": "************2160",
   "credit_card_type": null
 }
FieldDescription
credit_cardLast 4 digits of the new card (if card payment)
credit_card_typeCard brand: VISA, MASTERCARD, etc.

subscriptions/payment_status_changed

Sent when payment status changes

{
   "charset": "UTF-8",
   "utf": "√",
   "order_ref_1": "990093571",
   "order_ref_2": null,
   "order_ref": "3e88b4a9-58d6-4fcb-b347-52189e9c3952",
   "event": "subscriptions/payment_status_changed",
   "event_id": "102cc717-940d-40a6-9f97-bc59e89eea70",
   "successful": true,
   "updated_at": "2026-02-16T11:44:34.146+01:00"
 }

subscriptions/payment_success

Fired whenever a payment against a subscription is successfully confirmed. The event fires once per confirmed payment and is emitted regardless of whether the order has outstanding debt — i.e. partial payments also produce one event each.

Payload

FieldDescription
eventAlways "subscriptions/payment_success"
event_idUnique id for this delivery, useful for idempotency
amountAmount of the confirmed payment, in the order's currency. Two decimal places (e.g. `49.90`)
last_four_panLast four digits of the card used for the payment. null when no card reference is associated with the event
card_brandCard issuer name (e.g. "VISA", "MASTERCARD"). null when no card reference is associated with the event
transaction_idseQura's transaction reference for this payment
paid_atTimestamp when the payment was recorded

Example

{
  "event": "subscriptions/payment_success",
  "event_id": "8f3a7c2e-4b1d-4e9a-9c5f-2a8b6d1e3f47",
  "amount": 49.90,
  "last_four_pan": "4242",
  "card_brand": "VISA",
  "transaction_id": "txn_9f2e1c0a8b",
  "paid_at": "2026-06-29T10:15:32Z"
}

subscriptions/payment_error

Fired when a subscription payment cannot be collected. There are two situations that trigger this event:

  1. Charge declined at gateway — a scheduled charge reached the payment gateway and was rejected (e.g. card declined, insufficient funds, expired card). Payload reflects the card that was attempted and the gateway transaction reference.
  2. Charge skipped, no valid payment instrument — the scheduled charge could not be attempted because the subscription has no active card and no active direct-debit mandate. In this case card_brand is set to the sentinel value "no_card", and last_four_pan and transaction_id are null.

Consumers can distinguish the two cases from the card_brand field.

Payload

FieldDescription
eventAlways "subscriptions/payment_error"
event_idUnique id for this delivery, useful for idempotency
amountAmount that failed to be collected, in the order's currency. Two decimal places (e.g. 42.50). In the skip case, this is the amount that would have been charged
last_four_panLast four digits of the card that was charged. null when no card was involved (direct-debit mandate case, or skip case)
card_brandCard issuer name (e.g. "VISA", "MASTERCARD"). null when no card was involved. The sentinel "no_card" indicates the skip case — the attempt did not reach the gateway because no valid payment instrument was available
transaction_idseQura's transaction reference for the failed attempt. null in the skip case, since no attempt was made
failed_atISO8601 timestamp when the failure was recorded

Example — gateway decline

{
  "event": "subscriptions/payment_error",
  "event_id": "8f3a7c2e-4b1d-4e9a-9c5f-2a8b6d1e3f47",
  "amount": 42.50,
  "last_four_pan": "4242",
  "card_brand": "VISA",
  "transaction_id": "txn_9f2e1c0a8b",
  "failed_at": "2026-07-03T10:15:32Z"
}

Example — skipped, no valid payment instrument

{
  "event": "subscriptions/payment_error",
  "event_id": "d1c4a9b7-2e5f-4a83-9c1d-7b6e8f2a3c15",
  "amount": 30.00,
  "last_four_pan": null,
  "card_brand": "no_card",
  "transaction_id": null,
  "failed_at": "2026-07-03T10:15:32Z"
}

aml_documentation_required

Sent when seQura's AML process requires the customer to submit identity documentation. The subscription's aml_status becomes required.

{
  "charset": "UTF-8",
  "utf": "√",
  "event": "aml_documentation_required",
  "event_id": "1234",
  "order_ref_1": "pos_1234",
  "order_ref_2": "",
  "order_ref": "060eef19-da6c-4a5b-9a43-8bf43cb63a2e",
}

Recommended action: Inform the customer that they must provide documentation. seQura will contact them directly. Any changes in subscription will be rejected until AML process is completed.


aml_documentation_validated

Sent when the customer's AML documentation has been reviewed and approved. The subscription's aml_status becomes validated.

{
  "charset": "UTF-8",
  "utf": "√",
  "event": "aml_documentation_validated",
  "event_id": "1234",
  "order_ref_1": "pos_1234",
  "order_ref_2": "",
  "order_ref": "060eef19-da6c-4a5b-9a43-8bf43cb63a2e",
}

Recommended action: No action required. The subscription resumes normal operation.

order/account_in_debt

Sent when Part Payment order balance becomes negative (monthly charge is applied, but not yet paid)

 {
   "charset": "UTF-8",
   "utf": "√",
   "order_ref_1": "990093571",
   "order_ref_2": null,
   "order_ref": "3e88b4a9-58d6-4fcb-b347-52189e9c3952",
   "event": "order/account_in_debt",
   "event_id": "761865cc-7c9f-4a1f-9306-c24a10ed4bfa",
   "balance": "-23.76"
 }

order/account_up_to_date

Sent when balance becomes 0 or positive (all due charges are paid)

 {
   "charset": "UTF-8",
   "utf": "√",
   "order_ref_1": "990093571",
   "order_ref_2": null,
   "order_ref": "3e88b4a9-58d6-4fcb-b347-52189e9c3952",
   "event": "order/account_up_to_date",
   "event_id": "4e789cb4-90d3-4d86-bcfb-d92d828b9d30",
   "balance": "0"
 }

Pre-Confirmation Events

These events fire during the checkout process, before a subscription is confirmed. Subscribe to them the same way as any other event type.

Common fields

FieldTypeDescription
eventstringEvent type name
order_refstringseQura order UUID
order_ref_1stringYour primary order reference (if provided)
order_ref_2stringYour secondary order reference (if provided)
merchant_refstringYour merchant reference
charsetstringAlways "UTF-8"

denied

Fired when seQura's risk engine rejects the checkout application.

FieldTypeDescription
apm_offeredbooleantrue if an alternative payment method was offered to the customer

Example:

{
  "event": "denied",
  "order_ref": "8a3f1b2c-4d5e-...",
  "order_ref_1": "POS-7821",
  "order_ref_2": null,
  "apm_offered": false,
  "charset": "UTF-8"
}

cancelled

Fired when a checkout is cancelled before confirmation — by the operator, the customer, or a system timeout.

Distinct from subscriptions/cancelled, which applies to an already-confirmed subscription. This event is only sent for orders that went through an on-hold phase, a screening assessment, or originated from an instore sales flow.

No additional fields beyond the common set.

Example:

{
  "event": "cancelled",
  "order_ref": "8a3f1b2c-4d5e-...",
  "order_ref_1": "POS-7821",
  "order_ref_2": null,
  "charset": "UTF-8"
}

needs_card

Sent during initial subscription confirmation process, or changes confirmation process when the customer must update or confirm their payment card (e.g. PSD2 strong authentication required). The subscription status becomes waiting_for_payment.

{
  "charset": "UTF-8",
  "utf": "√",
  "event": "needs_card",
  "order_ref_1": "pos_1234",
  "order_ref_2": "",
  "order_ref": "060eef19-da6c-4a5b-9a43-8bf43cb63a2e",
  "given_names": "María",
  "surnames": "García López",
  "email": "[email protected]",
  "mobile_phone": "+34666123456",
  "nin": "12345678A",
  "date_of_birth": "1990-01-01",
  "address": "Calle Mayor 1",
  "city": "Barcelona",
  "postal_code": "08001"
}


Did this page help you?