This guide focuses on the full scope of running a recurring payment and provides steps from start to finish. This includes tokenizing the card, authorizing a transaction, converting your card token to multi-use, and performing a recurring payment when needed.
For information on the various use cases for recurring payments, see our Overview.
Before starting the steps in this guide, you must do the following:
A single-permission access token must first be generated in order to create a single-use payment token in the next step. An access token is a unique, single-use key used to access our API.
curl --location POST 'https://apis.sandbox.globalpay.com/ucp/accesstoken' \
--header 'Content-Type: application/json' \
--header 'Accept: application/json' \
--header 'X-GP-Version: 2021-03-22' \
--data '{
"app_id": "{{app_id}}",
"secret": "{{secret}}",
"grant_type": "client_credentials",
"nonce": "{{nonce}}",
"interval_to_expire": "10_MINUTES",
"permissions": [
"PMT_POST_Create_Single"
]
}{
"token": "4eQo0UX29btysKqJhDbjr688z7re",
"type": "Bearer",
"scope": {
"merchant_id": "MER_c5d37eaf0e3841e083c232b2318af55c",
"merchant_name": "Sandbox_Merchant_4",
"accounts": [
{
"id": "TKA_c1de85a8a5844c56abd9ca07bbd792c8",
"name": "tokenization",
"permissions": [
"PMT_POST_Create_Single"
]
}
]
},
"app_id": "T6og1tbECpHFeO104qUM383oq5bOJ12r",
"app_name": "Postman_Collection_Test",
"time_created": "2025-03-20T11:20:20.603Z",
"seconds_to_expire": 599,
"interval_to_expire": "10_MINUTES",
"email": "jordan.forde@globalpay.com"
}Once you’ve created the single-permission access token, you can use it to tokenize the card.
Tokenization replaces sensitive data with unique identification symbols, or tokens, that retain all the essential information about the data without compromising its security. This gives you the ability to securely store and manage payment methods on our API in any region.
Next, we will create a second access token with all the permissions for any transactions.
curl --location POST 'https://apis.sandbox.globalpay.com/ucp/payment-methods' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer 4eQo0UX29btysKqJhDbjr688z7re' \
--header 'Accept: application/json' \
--header 'X-GP-Version: 2021-03-22' \
--data '{
"usage_mode":"SINGLE",
"account_name": "{{token_acc_name}}",
"reference": "{{reference}}",
"card": {
"number": "4242424242424242",
"expiry_month": "{{expiry_month}}",
"expiry_year": "{{expiry_year}}",
"cvv":"{{cvv}}"
}
}'{
"id": "PMT_4d1c481a-a275-42b2-a795-85aef97b5db8",
"time_created": "2025-03-20T11:20:22.775Z",
"status": "ACTIVE",
"usage_mode": "SINGLE",
"merchant_id": "MER_c5d37eaf0e3841e083c232b2318af55c",
"merchant_name": "Sandbox_Merchant_4",
"account_id": "TKA_c1de85a8a5844c56abd9ca07bbd792c8",
"account_name": "tokenization",
"reference": "96068801",
"card": {
"masked_number_last4": "XXXXXXXXXXXX4242",
"brand": "VISA",
"expiry_month": "12",
"expiry_year": "30"
},
"action": {
"id": "ACT_xn2IAZsZfkMy309zl12q0Jrb9FF3wA",
"type": "PAYMENT_METHOD_CREATE",
"time_created": "2025-03-20T11:20:22.775Z",
"result_code": "SUCCESS",
"app_id": "T6og1tbECpHFeO104qUM383oq5bOJ12r",
"app_name": "Postman_Collection_Test"
}
}Now, we will create a second access token with all the permissions to use for authorizing transactions.
curl --location POST 'https://apis.sandbox.globalpay.com/ucp/accesstoken' \
--header 'Content-Type: application/json' \
--header 'Accept: application/json' \
--header 'X-GP-Version: 2021-03-22' \
--data '{
"app_id": "{{app_id}}",
"secret": "{{secret}}",
"grant_type": "client_credentials",
"nonce": "{{nonce}}"
}'{
"token": "3W4y5tOoIOBxiBQPvqlrEyN1JkVd",
"type": "Bearer",
"scope": {
"merchant_id": "MER_c5d37eaf0e3841e083c232b2318af55c",
"merchant_name": "Sandbox_Merchant_4",
"accounts": [
{
"id": "TRA_27c901760029495f813afbb0dab197ef",
"name": "transaction_processing",
"permissions": [
"TRN_POST_Authorize",
"TRN_POST_Force",
"TRN_POST_Refund",
"TRN_POST_Capture",
"TRN_POST_Reverse",
"TRN_POST_Adjust",
"TRN_POST_Initiate",
"BAT_POST_Close",
"TRN_POST_Refund_Standalone",
"VER_POST_Verify",
"TRN_POST_Reauthorize",
"INS_POST_Query",
"TRN_GET_Single",
"TRN_POST_Confirm",
"DEV_POST_Sync",
"ACT_GET_Single",
"ACT_GET_List",
"TRN_GET_List",
"TRN_POST_Capture_Multiple",
"ACT_POST_Multiple",
"APP_GET_Single",
"AUT_POST_Initiate",
"CCS_POST_DCC",
"ACC_GET_Single_Platform",
"ACC_GET_Single",
"APP_POST_Search_PFCValidate",
"ACT_POST_Auto_Action",
"PFC_GET_List",
"PFC_GET_Single",
"TRN_POST_Incremental",
"AUT_POST_Results",
"BAT_GET_Single",
"ACC_GET_List",
"GET_Single",
"AUT_POST_Check_Availability",
"APP_GET_List",
"TRN_POST_Split",
"AUT_GET_Single",
"AUT_GET_List",
"TRN_POST_Hold",
"TRN_POST_Release"
]
},
{
"id": "TKA_c1de85a8a5844c56abd9ca07bbd792c8",
"name": "tokenization",
"permissions": [
"PMT_POST_Create",
"PMT_PATCH_Edit",
"PMT_Delete",
"PMT_GET_List",
"PMT_GET_Single",
"PMT_POST_Search",
"ACT_POST_Multiple",
"PMT_POST_Create_Single",
"ACC_GET_Single",
"GET_Single",
"ACT_POST_Auto_Action",
"APP_POST_Search_PFCValidate",
"ACC_GET_List",
"ACT_GET_List",
"ACT_GET_Single",
"PYR_GET_Single",
"PYR_POST_Edit",
"PYR_GET_List",
"PYR_POST_Create"
]
}
]
},
"app_id": "T6og1tbECpHFeO104qUM383oq5bOJ12r",
"app_name": "Postman_Collection_Test",
"time_created": "2025-03-20T11:20:24.635Z",
"seconds_to_expire": 86399,
"email": "jordan.forde@globalpay.com"
}Simply storing a tokenized card for use in recurring payments will not validate the card. This is why it’s important to perform a verification to ensure the information on the card is accurate and the cardholder has sufficient funds for the transaction. Both are necessary to authorize the transaction.
In this example, we send a request for a standard transaction using the single-use payment token in the request body to verify the card and authorize the initial transaction. Note that the brand reference generated in this step will be used in the recurring transaction request.
curl --location POST 'https://apis.sandbox.globalpay.com/ucp/transactions' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer 3W4y5tOoIOBxiBQPvqlrEyN1JkVd' \
--header 'Accept: application/json' \
--header 'X-GP-Version: 2021-03-22' \
--data '{
"account_name": "{{acc_name}}",
"channel": "CNP",
"capture_mode":"AUTO",
"type": "SALE",
"amount": "100",
"currency": "USD",
"reference": "{{reference}}",
"country": "US",
"payment_method": {
"name": "Jane",
"entry_mode": "ECOM",
"id": "PMT_4d1c481a-a275-42b2-a795-85aef97b5db8"
}
}{
"id": "TRN_Wa3UZsF0PnM4NDARGmLwjuhvRarHlV_10984351",
"time_created": "2025-03-20T11:20:28.538Z",
"type": "SALE",
"status": "CAPTURED",
"channel": "CNP",
"capture_mode": "AUTO",
"amount": "100",
"currency": "USD",
"country": "US",
"merchant_id": "MER_c5d37eaf0e3841e083c232b2318af55c",
"merchant_name": "Sandbox_Merchant_4",
"account_id": "TRA_27c901760029495f813afbb0dab197ef",
"account_name": "transaction_processing",
"reference": "10984351",
"payment_method": {
"result": "00",
"message": "(00)[ test system ] Authorised",
"entry_mode": "ECOM",
"card": {
"funding": "CREDIT",
"brand": "VISA",
"masked_number_last4": "XXXXXXXXXXXX4242",
"authcode": "123456",
"brand_reference": "mH21POhUcoogvgt6",
"brand_time_created": "",
"tag_response": "",
"cvv_result": "MATCHED",
"avs_address_result": "MATCHED",
"avs_postal_code_result": "MATCHED",
"avs_action": "",
"provider": {
"result": "00",
"cvv_result": "M",
"avs_address_result": "M",
"avs_postal_code_result": "M"
}
}
},
"risk_assessment": [
{
"mode": "ACTIVE",
"result": "ACCEPTED",
"rules": [
{
"reference": "0c93a6c9-7649-4822-b5ea-1efa356337fd",
"description": "Cardholder Name Rule",
"mode": "ACTIVE",
"result": "ACCEPTED"
},
{
"reference": "a539d51a-abc1-4fff-a38e-b34e00ad0cc3",
"description": "CardNumber block",
"mode": "ACTIVE",
"result": "ACCEPTED"
},
{
"reference": "d023a19e-6985-4fda-bb9b-5d4e0dedbb1e",
"description": "Amount test",
"mode": "ACTIVE",
"result": "ACCEPTED"
}
]
}
],
"batch_id": "BAT_1510378",
"action": {
"id": "ACT_Wa3UZsF0PnM4NDARGmLwjuhvRarHlV",
"type": "AUTHORIZE",
"time_created": "2025-03-20T11:20:28.538Z",
"result_code": "SUCCESS",
"app_id": "T6og1tbECpHFeO104qUM383oq5bOJ12r",
"app_name": "Postman_Collection_Test"
}
}Once the card is verified, the card can now be stored by converting the single use payment token to a multi use payment token using a PATCH call as shown in the below example.
curl --location PATCH 'https://apis.sandbox.globalpay.com/ucp/payment-methods/PMT_4d1c481a-a275-42b2-a795-85aef97b5db8'
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer 3W4y5tOoIOBxiBQPvqlrEyN1JkVd' \
--header 'Accept: application/json' \
--header 'X-GP-Version: 2021-03-22' \{
"id": "PMT_4d1c481a-a275-42b2-a795-85aef97b5db8",
"status": "ACTIVE",
"usage_mode": "MULTIPLE",
"card": {
"expiry_month": "",
"expiry_year": ""
},
"action": {
"id": "ACT_6qwDoGM9pqBkqoLPHEflxQFQKqguDk",
"type": "PAYMENT_METHOD_EDIT",
"time_created": "2025-03-20T11:20:50.538Z",
"result_code": "SUCCESS",
"app_id": "T6og1tbECpHFeO104qUM383oq5bOJ12r",
"app_name": "Postman_Collection_Test"
}
}The recurring payment process is not automated in our API. The request for payment must be sent at the time the recurring payment is due.
This is typically handled by your software, which will require the payment token identifier and a brand reference fetched in the initial authorization (Step 4) when making its recurring requests for payment.
Because the next transaction might occur days or weeks after the initial authorization, a new full access token might be required to complete subsequent authorizations.
curl --location POST 'https://apis.sandbox.globalpay.com/ucp/transactions
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer 3W4y5tOoIOBxiBQPvqlrEyN1JkVd' \
--header 'Accept: application/json' \
--header 'X-GP-Version: 2021-03-22' \
--data '{
"account_name": "{{acc_name}}",
"channel": "CNP",
"capture_mode": "AUTO",
"type": "SALE",
"amount": "100",
"currency": "USD",
"reference": "{{reference}}",
"country": "US",
"initiator": "MERCHANT",
"stored_credential": {
"model": "RECURRING",
"reason": "INCREMENTAL",
"sequence": "SUBSEQUENT"
},
"payment_method": {
"name": "Jane",
"entry_mode": "ECOM",
"id": "{{pmt_id}}",
"card": {
"brand_reference": "{{brand_ref}}"
}
}
} {
"id": "TRN_fT7SsRTYZkBBzNO5Jtkky3Br54veOp_78442951",
"time_created": "2025-03-20T11:21:00.538Z",
"type": "SALE",
"status": "CAPTURED",
"channel": "CNP",
"capture_mode": "AUTO",
"amount": "100",
"currency": "USD",
"country": "US",
"merchant_id": "MER_c5d37eaf0e3841e083c232b2318af55c",
"merchant_name": "Sandbox_Merchant_4",
"account_id": "TRA_27c901760029495f813afbb0dab197ef",
"account_name": "transaction_processing",
"reference": "78442951",
"payment_method": {
"result": "00",
"message": "(00)[ test system ] Authorised",
"entry_mode": "ECOM",
"card": {
"brand": "VISA",
"masked_number_last4": "XXXXXXXXXXXX4242",
"authcode": "123456",
"brand_reference": "CildSOKDR0xyrWGK",
"brand_time_created": "",
"provider": {
"result": "00",
"cvv_result": "M",
"avs_address_result": "M",
"avs_postal_code_result": "M"
}
}
},
"risk_assessment": [
{
"mode": "ACTIVE",
"result": "ACCEPTED",
"rules": [
{
"reference": "0c93a6c9-7649-4822-b5ea-1efa356337fd",
"description": "Cardholder Name Rule",
"mode": "ACTIVE",
"result": "ACCEPTED"
},
{
"reference": "a539d51a-abc1-4fff-a38e-b34e00ad0cc3",
"description": "CardNumber block",
"mode": "ACTIVE",
"result": "ACCEPTED"
},
{
"reference": "d023a19e-6985-4fda-bb9b-5d4e0dedbb1e",
"description": "Amount test",
"mode": "ACTIVE",
"result": "ACCEPTED"
}
]
}
],
"batch_id": "BAT_1530138",
"action": {
"id": "ACT_fT7SsRTYZkBBzNO5Jtkky3Br54veOp",
"type": "AUTHORIZE",
"time_created": "2025-03-20T11:21:00.538Z",
"result_code": "SUCCESS",
"app_id": "T6og1tbECpHFeO104qUM383oq5bOJ12r",
"app_name": "Postman_Collection_Test"
}
}For a deeper understanding of this function, use the integration references we provide for our API and SDK integrations. You can see the full detailed API specification in our API Explorer.
Generate an access token.
See the full transaction endpoint, including recurring payments.
Add server-side or client-side code to your integration.
You can test our Recurring Payments solution in our free Sandbox environment. All it takes is a registered user in our developer portal. Get started with the resources below.
Test different transaction outcomes with simulated cards or banks.
View, import, or fork our API collection in Postman.
View successful responses, HTTP status codes, action response data, and errors.