This guide is for current implementations. For legacy implementations see Recurring Payments (Legacy). There is also a migration guide at Migration to Secupay Acquiring.

Prerequisites

As a prerequisite, you should understand:

You should also understand if you may have searched for Subscriptions.

Abstract

Your contract needs to be activated for recurring payments. Otherwise the subsequent payment with MIT cannot be authorised.

To use a credit card for recurring payments, you must:

  • Make the first payment with a Customer Initiated Transaction (CIT). You must also request a Network Token, and record both Payment Container ID (PCT_…) and Payment Transaction ID (PCI_…).
  • Make the subsequent payments as Merchant Initiated Transactions (MIT). You must also pass the recorded IDs at different stages of the process.

Subsequent Payments can be captured without customer interaction. The Strong Customer Authentication (SCA) by the Revised Payment Services Directive (PSD2) is omitted.

To make recurring payments with direct debit, you only need to record the Payment Container ID and pass it back later.

The following examples are for the more compley case of repeated credit card payments. For direct debit please disregard everything special except storing and using the Payment Conatiner ID.

Make the Initial Payment

Create the Smart Transaction

When you make the first payment, you must add the needed "mit_instructions" and  "container_instructions" to the "payment_context" when you create the Smart Transaction. The first payment is made with customer interaction, and thus called and regulated a Customer-Initiated Transaction (CIT).

There are these two cases:

  • Scheduled: A series of recurring payments with a fixed amount and frequency, such as a subscription service.
  • Unscheduled: A series of irregular transactions using stored card details, such as an automatic account top-up or a rideshare fee. Often this is referred to as Unscheduled Card On File, or for short UCOF.

For the API integration, this makes only a difference for the first payment.

First an example for unscheduled recurring payments:

Request (Unscheduled)
POST /api/v2/Smart/Transactions HTTP/1.1
Host: connect-testing.secuconnect.com
Authorization: Bearer qb56tjj1bcvo9n2nj4u38k84lo
Content-Type: application/json
Accept: application/json
 
{
"contract": {
"id": "GCR_KTSST836QYITQJM1JGYIZ4F4OLKI04"
},
"customer": {
"contact": {
"company_name": "Musterfirma GmbH"
            "forename": "Max",
"surname": "Mustermann",
"address": {
"street": "Musterallee",
"street_number": "23-25",
"postal_code": "09005",
"city": "Musterstadt",
"country": "DE"
},
"email": "m.muster@example.net",
"mobile": "+491775555555",
"phone": "+495555555555"
}
},
"transactionRef": "Bestellung am 25.02.2026 bei ACME Buero-Paradies auf Example.com",
"merchantRef": "20000345",
"basket": {
"products": [
{
"id": 1,
"articleNumber": 30037,
"ean": "4999012345678",
"desc": "Druckerpapier Eco A4 80g",
"quantity": 10,
"priceOne": 7900,
"tax": 19
},
{
"id": 2,
"item_type": "shipping",
"desc": "Versand Spedition",
"quantity": 1,
"priceOne": 500,
"tax": 19
}
]
},
"basket_info": {
"sum": 8400,
"currency": "EUR"
},
"payment_context": {
"auto_capture": true,
"dynamic_descriptor": {
"merchant_name": "ACME Buero-Paradies",
"merchant_city": "Bielefeld"
},
"mit_instructions": {
"type": "cit",
"standing_instruction": "ucof"
},
"container_instructions": {
"request_token": true,
"notification_url": "https://shop.example.com/network-token/update?orderid=12345"
}
    }
}

Please note the elements "mit_instructions" and "container_instructions" inside "payment_context" at line 66 .. 75.

Now the same example with only the necessary or changed fields for scheduled recurring payments:

Request (Scheduled)
POST /api/v2/Smart/Transactions HTTP/1.1
Host: connect-testing.secuconnect.com
Authorization: Bearer qb56tjj1bcvo9n2nj4u38k84lo
Content-Type: application/json
Accept: application/json
 
{
// ...
"payment_context": {
// ...
"mit_instructions": {
"type": "cit",
"standing_instruction": "recurring",
"recurring_expiry": "2029-07-31",
"recurring_frequency": "30"
},
"container_instructions": {
"request_token": true,
"notification_url": "https://shop.example.com/network-token/update?orderid=12345"
}
    }
}

If everything is fine, the API responds with 200 OK and the created Smart Transaction.

Details of the related fields:

Field

Type

Meaning

mit_instructions

object

Instructions for MIT transactions needed when making the payment in the next step.

container_instructions

object

Instructions considered when creating the Payment Container in the next step.

Details of "mit_instructions":

Field

Type

Meaning

type

string

Marks a transaction as the Customer-Initiated Transaction ("cit") to be referred later to, or as one of the relating Merchant-Initiated Transactions ("mit")

standing_instruction

string

Tells whether there is a fix or flexible standing transaction:

  • "recuring" for scheduled payments
  • "ucof" for Unscheduled Card On File (UCOF)

recurring_expiry

string

ISO-8601 date; expiry date for the card

Note: Please consider more reasons for it to become invalidated

recurring_frequency

string

Frequency of the subsequent payments in days

Details of "container_instructions":

Field

Type

Meaning

request_token

boolean

Requests to save the credit card reference securely on the servers of a credit card network like VISA or MasterCard (“Network Token“)

notification_url

string

Callback URL on your server for status updates for the Payment Container related to the Network Token

Authorise and Capture the Payment

 Imagine you have authorised the Smart Transaction for the first order by using this call, for example:

Request
POST /api/v2/Smart/Transactions/STX_3Z8EUQX0A2PBHRJV9FRY7P56GEDZAK/prepare/creditcard HTTP/1.1
Host: connect-testing.secuconnect.com
Authorization: Bearer qb56tjj1bcvo9n2nj4u38k84lo
Content-Type: application/json
Accept: application/json
 
{
"container": {
"type": "credit_card",
"private": {
"owner": "Max Mustermann",
"pan": "463544XXXXXX2298",
"expiration_date": "2034-02-01T00:00:00+00:00",
"issuer": "VISA",
"transact_container": "MzkzOTQ0MGI1YTBmMDg2ZDkxYTEwNzIyZTMwNTgwNGZjYTU3...",
"transact_skey_pubkey": "8ebccbb725d89d6286f227e672f24155e8b50b9688e7a45b...",
"transact_skey_keyname": "spp_2025.pem",
"transact_hash": "671439c1a91466df0249d8ab1b3595b682def08b1aea05a2d66e6adcf3d37a98"
}
},
"callback_urls": {
"success_url": "https://shop.example.com/payment/success?nonce=ciix8j3qbqffg8dcdc7b",
"failure_url": "https://shop.example.com/payment/failure?nonce=ciix8j3qbqffg8dcdc7b"
}
}

If everything was fine, the API would have responded with something with 200 OK and the updated Smart Transaction:

Response
HTTP/1.1 200 OK
Content-Type: application/json
 
{
"object": "smart.transactions",
"id": "STX_3Z8EUQX0A2PBHRJV9FRY7P56GEDZAK",
// ...
"container": {
"object": "payment.containers",
"id": "PCT_3JU4VGYZF2XY8EJHH9FQ7WGYNZGJA4",
"type": "credit_card"
// ...
"token_status": {
"status": "requested",
// ...
    },
"transactions": [
{
"object": "payment.transactions",
"id": "PCI_W026W643US3TWCGZA0AVZ248W8TSMW",
"trans_id": 123456789,
"transaction_hash": "abcdefghijkl12345678"
}
],
"created": "2025-02-25T15:55:58+01:00",
"updated": "2025-02-25T15:56:16+01:00",
"status": "created",
// ...
"payment_method": "creditcard",
"trans_id": 123456789,
"iframe_url": "https://connect-testing.secuconnect.com/spp/challenge/?token=5ab8b08...",
// ...
}

For direct debit it would look similar but there is no 3-D Secure, and thus no iframe_url. Credit card payments require a 3-D Secure check if not exempted. So the iframe_url may be present or not. If auto_capture is set, the payment would be captured immediately after successful authorisation.

Please note the fields with the Payment Container ID (container.id) and the Payment Transaction ID (transactions[0].id). (If there is more than one transaction, please use first one.)

In case of credit card payment, you need to save both IDs in relation to your customer account. You would also need to manage the life cycle of the Payment Container ID.

In case of direct debit, you only need to save the Payment Container ID.

Handle Failed Token Request upon Initial Payment

When you authorise (and perhaps auto-capture) the first payment, the payment may succeed whilst the Network Token request would fail. In this case the Payment Container details would be useless, and standing order or subscription would not work.

Please take these considerations into account:

  • The Network Token creation might fail from the beginning
  • The Network Token might be invalidated later for a number of reasons (token expiry, card not renewed, etc.)

You must handle this situation.

One way to split the initial payment, or that for a token renewal, from the order, is to make a credit card authorisation with an amount of zero.

Imagine this authorisation request:

Request
POST /api/v2/Smart/Transactions/STX_3Z8EUQX0A2PBHRJV9FRY7P56GEDZAK/prepare/creditcard HTTP/1.1
Host: connect-testing.secuconnect.com
Authorization: Bearer qb56tjj1bcvo9n2nj4u38k84lo
Content-Type: application/json
Accept: application/json
 
{
"container": {
"type": "credit_card",
"private": {
"owner": "Max Mustermann",
"pan": "463544XXXXXX2298",
"expiration_date": "2034-02-01T00:00:00+00:00",
"issuer": "VISA",
"transact_container": "MzkzOTQ0MGI1YTBmMDg2ZDkxYTEwNzIyZTMwNTgwNGZjYTU3...",
"transact_skey_pubkey": "8ebccbb725d89d6286f227e672f24155e8b50b9688e7a45b...",
"transact_skey_keyname": "spp_2025.pem",
"transact_hash": "671439c1a91466df0249d8ab1b3595b682def08b1aea05a2d66e6adcf3d37a98"
}
},
"callback_urls": {
"success_url": "https://shop.example.com/payment/success?nonce=ciix8j3qbqffg8dcdc7b",
"failure_url": "https://shop.example.com/payment/failure?nonce=ciix8j3qbqffg8dcdc7b"
}
}

In this case the API might respond with 200 OK and the updated Smart Transaction like this:

Response
HTTP/1.1 200 OK
Content-Type: application/json
 
{
"object": "smart.transactions",
"id": "STX_3Z8EUQX0A2PBHRJV9FRY7P56GEDZAK",
// ...
"container": {
"object": "payment.containers",
"id": "PCT_3JU4VGYZF2XY8EJHH9FQ7WGYNZGJA4",
"type": "credit_card",
// ...
"token_status": {
"status": "failed",
// ...
}
},
"transactions": [
{
"object": "payment.transactions",
"id": "PCI_W026W643US3TWCGZA0AVZ248W8TSMW",
"trans_id": 123456789,
"transaction_hash": "abcdefghijkl12345678"
}
],
"created": "2025-02-25T15:55:58+01:00",
"updated": "2025-02-25T15:56:16+01:00",
"status": "created",
// ...
"payment_method": "creditcard",
"trans_id": 123456789,
"iframe_url": "https://connect-testing.secuconnect.com/spp/challenge/?token=5ab8b08...",
// ...
}

Please note container.token_status.status being "failed" (line 14).

In this case don't save the Payment Container details, and manage the situation.

Make the Subsequent Payments

Create the Smart Transaction

When you make later payments, you must also add different "mit_instructions" to the "payment_context" when you create the Smart Transaction:

Request
POST /api/v2/Smart/Transactions HTTP/1.1
Host: connect-testing.secuconnect.com
Authorization: Bearer qb56tjj1bcvo9n2nj4u38k84lo
Content-Type: application/json
Accept: application/json
 
{
"contract": {
"id": "GCR_KTSST836QYITQJM1JGYIZ4F4OLKI04"
},
"customer": {
"contact": {
"company_name": "Musterfirma GmbH"
            "forename": "Max",
"surname": "Mustermann",
"address": {
"street": "Musterallee",
"street_number": "23-25",
"postal_code": "09005",
"city": "Musterstadt",
"country": "DE"
},
"email": "m.muster@example.net",
"mobile": "+491775555555",
"phone": "+495555555555"
}
},
"transactionRef": "Nachlieferung am 10.05.2026 bei ACME Buero-Paradies auf Example.com",
"merchantRef": "20000456",
"basket": {
"products": [
{
"id": 1,
"articleNumber": 30037,
"ean": "4999012345678",
"desc": "Druckerpapier Eco A4 80g",
"quantity": 8,
"priceOne": 6380,
"tax": 19
},
{
"id": 2,
"item_type": "shipping",
"desc": "Versand Spedition",
"quantity": 1,
"priceOne": 500,
"tax": 19
}
]
},
"basket_info":
{
"sum": 6880,
"currency": "EUR"
},
"payment_context":
{
"auto_capture": true,
"dynamic_descriptor":
{
"merchant_name": "ACME Buero-Paradies",
"merchant_city": "Bielefeld"
},
"mit_instructions":
{
"type": "mit",
"cit_reference": "PCI_6UKN8UE29BH6EKF42JS6325AG34WMY"
}
    }
}

If everything is fine, the API responds with 200 OK and the created Smart Transaction.

Please note the following different elements inside "mit_instructions" at line 66 .. 70:

Field

Type

Meaning

type

string

MIT transactions ("mit") for subsequent payment now

cit_reference

string

Payment Transaction ID (PCI_…) of the first payment

The other object "container_instructions" is no longer needed.

If everything is fine, the API responds with 200 OK and the created Smart Transaction. There is nothing special in the responded Smart Transaction.

Authorise and Capture the Payment

With the call to authorise the payment, you would pass the Payment Container ID only instead of all the details:

Authorisation Request
POST /api/v2/Smart/Transactions/STX_HUXEQ5X302PBHTEYWP66F9AX0N44A4/prepare/creditcard HTTP/1.1
Host: connect-testing.secuconnect.com
Authorization: Bearer qb56tjj1bcvo9n2nj4u38k84lo
Content-Type: application/json
Accept: application/json
 
{
"container": {
"id": "PCT_3JU4VGYZF2XY8EJHH9FQ7WGYNZGJA4",
},
"callback_urls": {
"success_url": "https://shop.example.com/payment/success?nonce=ciix8j3qbqffg8dcdc7b",
"failure_url": "https://shop.example.com/payment/failure?nonce=ciix8j3qbqffg8dcdc7b"
}
}

If everything is fine, the API responds again with 200 OK and the updated Smart Transaction:

Response
HTTP/1.1 200 OK
Content-Type: application/json
 
{
"object": "smart.transactions",
"id": "STX_HUXEQ5X302PBHTEYWP66F9AX0N44A4",
// ...
"container": {
"object": "payment.containers",
"id": "PCT_3JU4VGYZF2XY8EJHH9FQ7WGYNZGJA4",
"type": "credit_card"
// ...
"token_status": {
"status": "active",
// ...
}
    },
"transactions": [
{
"object": "payment.transactions",
"id": "PCI_54UPYB6SGWC7PQCBXHX99248W8UWMJ",
"trans_id": 123456791,
"transaction_hash": "bcdefghijklm223456789"
}
],
"created": "2026-05-10T16:58:34+01:00",
"updated": "2026-05-10T17:00:40+01:00",
"status": "ok",
// ...
"payment_method": "creditcard",
"trans_id": 123456791,
// ...
}

The payment is authorised or already captured (if accompanied by the auto_capture flag). Please check the payment status.

Network Token Lifecycle

Manage Status Changes of the Network Token

Beginning with our new acquiring solution, we will also start to send push notifications for Network Token status changes. This can be used to activate or to remove the Payment Container. The push notification is sent for the Payment Container holding the Network Token.

All details are found here: Network Token Status Notifications

Archiving the Network Token

Beginning with our new acquiring solution, you can request the deletion or archiving the network token.

All details are found here: Archiving the Network Token

See Also