Send Payment Links by SMS or Email
This guide describes the Pay by Link API: how to create a payment whose link is delivered to the shopper by SMS or email, and how to check its status with a GET call.
The payment link is generated by seQura and delivered directly to the shopper through the channel you choose (sms or email). If you prefer to deliver it through your own means, use the no_op channel: nothing is sent to the shopper and the payment link is returned to you in the Location response header. In every case, you follow up on the payment through the result webhook or the status endpoint.
Activation required: Pay by Link is not enabled by default. To start using this feature, ask your seQura account manager to activate it for your merchant account.
Authentication and environments
All calls require HTTP Basic Auth with your seQura merchant credentials (the username is your merchant reference). There is no separate sign-up step: on your first call with valid credentials, your merchant account is provisioned automatically.
| Environment | Base URL |
|---|---|
| Sandbox | https://partner-integration-middleware-sandbox.sequra.com |
| Production | https://partner-integration-middleware.sequra.com |
Invalid credentials return 401 with error_codes: ["credentials_invalid"]; a missing Authorization header returns 401 with ["credentials_required"].
Create a payment and deliver the link
Endpoint: /api/workflow_payments/v1/payments
Method: POST
Creates the payment and triggers the delivery of the payment link to the shopper. With channel: "sms" the phone field is required.
Body parameters (JSON)
| Field | Type | Required | Description |
|---|---|---|---|
channel | string | required | "sms", "email" or "no_op". Channel used to deliver the payment link. With "no_op" nothing is sent to the shopper — the link is returned in the Location response header instead. |
email | string | required | Shopper's email (required even when the channel is SMS). |
total_amount | integer | required | Total amount in cents, greater than 0. |
phone | string | required for SMS | Shopper's phone number. Missing it with channel: "sms" returns the phone_phone_required_for_sms error. |
reference | string | optional | Your order reference. Acts as an idempotency key (see the note below). |
given_names | string | optional | Shopper's first name. |
surnames | string | optional | Shopper's last name. |
currency | string | optional | Defaults to "EUR". |
product | string | optional | seQura product: tbs (default), pp3, pp5, pp6, pp9, sp1, i1. |
items | array | optional | Cart lines: name (required), reference, quantity, price_with_tax, total_with_tax. If omitted, a single "Payment" line is generated. |
notification_url | string | optional | Your webhook URL, notified with the payment result. |
campaign | string | optional | Campaign identifier forwarded with the link delivery. |
Example — send a payment link by SMS
curl -X POST "https://partner-integration-middleware-sandbox.sequra.com/api/workflow_payments/v1/payments" \
-u "YOUR_MERCHANT_REF:YOUR_PASSWORD" \
-H "Content-Type: application/json" \
-d '{
"channel": "sms",
"phone": "+34612345678",
"email": "[email protected]",
"given_names": "Ana",
"surnames": "García",
"reference": "ORDER-2026-0042",
"total_amount": 10050,
"currency": "EUR",
"product": "tbs",
"notification_url": "https://your-shop.com/webhooks/sequra"
}'Response: 201 Created with an empty body. The Location header contains the seQura order UUID.
HTTP/1.1 201 Created
Location: a3f1c9d2-8b47-4e02-9c11-5f6d7e8a9b0c
Example — with cart items
Each line accepts name (required), reference, quantity, price_with_tax and total_with_tax — amounts in cents, like total_amount. If items is omitted, a single "Payment" line is generated for the total.
curl -X POST "https://partner-integration-middleware-sandbox.sequra.com/api/workflow_payments/v1/payments" \
-u "YOUR_MERCHANT_REF:YOUR_PASSWORD" \
-H "Content-Type: application/json" \
-d '{
"channel": "sms",
"phone": "+34612345678",
"email": "[email protected]",
"given_names": "Ana",
"surnames": "García",
"reference": "ORDER-2026-0044",
"total_amount": 10050,
"currency": "EUR",
"product": "pp3",
"items": [
{
"name": "Running shoes",
"reference": "SKU-SHO-001",
"quantity": 2,
"price_with_tax": 2500,
"total_with_tax": 5000
},
{
"name": "Waterproof jacket",
"reference": "SKU-JAC-072",
"quantity": 1,
"price_with_tax": 5050,
"total_with_tax": 5050
}
],
"notification_url": "https://your-shop.com/webhooks/sequra"
}'Example — same payment by email
curl -X POST "https://partner-integration-middleware-sandbox.sequra.com/api/workflow_payments/v1/payments" \
-u "YOUR_MERCHANT_REF:YOUR_PASSWORD" \
-H "Content-Type: application/json" \
-d '{
"channel": "email",
"email": "[email protected]",
"reference": "ORDER-2026-0043",
"total_amount": 4999
}'Example — get the link without sending it (no_op)
no_op)With channel: "no_op", seQura does not deliver anything to the shopper. The payment link comes back in the Location response header, so you can read it and send it through your own means (your CRM, WhatsApp, a printed QR…).
curl -X POST "https://partner-integration-middleware-sandbox.sequra.com/api/workflow_payments/v1/payments" \
-u "YOUR_MERCHANT_REF:YOUR_PASSWORD" \
-H "Content-Type: application/json" \
-d '{
"channel": "no_op",
"email": "[email protected]",
"reference": "ORDER-2026-0045",
"total_amount": 7500
}'Response: 201 Created with an empty body. The Location header contains the payment link to share with the shopper.
HTTP/1.1 201 Created
Location: <payment link to share with the shopper>
Idempotency and resending the link: if you POST again with the same
referencewhile the payment is stillpending, no new payment is created — the link delivery is retried on the existing one and the API responds201again. This is the supported way to resend the payment link. If the payment is already authorized or captured, the API responds409withorder_conflict.
Check the payment status
Endpoint: /api/workflow_payments/v1/payments/{payment_id}
Method: GET
Returns the current state of the payment. The response is deliberately minimal and does not include the payment link.
Example
curl "https://partner-integration-middleware-sandbox.sequra.com/api/workflow_payments/v1/payments/7418632b-6c32-40b9-9942-be7007e355e7" \
-u "YOUR_MERCHANT_REF:YOUR_PASSWORD"Response: 200 OK
{
"payment_id": "7418632b-6c32-40b9-9942-be7007e355e7",
"reference": "ORDER-2026-0042",
"status": "authorized"
}Possible statuses
| Status | Meaning |
|---|---|
pending | Payment created; the shopper has not completed it yet. |
authorized | Payment approved by seQura. |
captured | Amount captured. |
on_hold | Under manual review. |
declined | Payment declined. |
cancelled / voided | Payment cancelled or voided. |
expired | The link expired before the payment was completed. |
Which identifier to use: the
payment_idaccepted by this endpoint is the one delivered in thepayment_idfield of the result webhook. It is a different identifier from the seQura order UUID returned in theLocationheader when the payment is created with thesmsorno_op, theLocationheader carries the payment link instead).
Payment result webhook
If the create request included a notification_url, seQura sends a JSON POST to that URL when the payment is resolved. Your endpoint must respond 200; otherwise the notification is retried up to 9 times with exponential backoff (60 s × 3n−1).
{
"payment_id": "7418632b-6c32-40b9-9942-be7007e355e7",
"order_id": "a3f1c9d2-8b47-4e02-9c11-5f6d7e8a9b0c",
"reference": "ORDER-2026-0042",
"status": "approved",
"amount": 10050,
"currency": "EUR",
"timestamp": "2026-07-14T10:00:00Z"
}payment_id— use it to query the status endpoint.order_id— the seQura order UUID (the one returned in theLocationheader).status—approved,needs_revieworfailed.
Errors
All errors share the same JSON envelope:
{
"request_id": "fcb7262b-…",
"error_type": "validation_error",
"error_codes": ["email_is_missing", "total_amount_is_missing"]
}| HTTP | error_type | Common codes |
|---|---|---|
400 | validation_error | channel_invalid_channel, phone_phone_required_for_sms, total_amount_amount_must_be_positive, product_invalid_product, reference_duplicate, field_is_missing |
401 | authentication_error | credentials_required, credentials_invalid |
404 | entity_error | payment_not_found (GET with an unknown payment_id) |
409 | entity_error | order_conflict (same reference on a payment already authorized or captured) |
422 | entity_error | partner_error (seQura rejected the payment creation or the link delivery) |
Updated about 12 hours ago