PSE Payment intents: subsequent payments

Collect payments in 🇨🇴 Colombia from your recurrent customers using a Belvo-integrated institution.

This guide will show you how to collect all payments from your customers who have already made a payment before. The payment intent flow is simpler because you don’t need to register them again or send through their bank account information (it’s already saved in the Belvo database) 😊.

PSE flow

  1. Create a payment intent
  2. Complete a payment intent
  3. Receive a webhook confirming the payment

📘

Webhooks notifications

We’ll let you know when certain webhooks (and their types) are sent to the webhook URL so you can keep track of the payment lifecycle along the way.

Check our Webhooks article for more info. 🤓

Create a payment intent

A payment intent is a request to collect payments from your customer, and it keeps in-depth information about your user's journey throughout the payment process.

The way it works is:

  1. You create a payment intent by making a POST Create a new payment intent request.
  2. You fill in the payment intent with all the information about your customer through subsequent PATCH Complete a payment intent requests.
Payment intent flow for a customer's subsequent payment

Payment intent flow for a customer's subsequent payment

To create a payment intent, you need to make a POST Create a new payment intent request with the following core information:

{
	"allowed_payment_method_types":["pse"],
	"amount": "amount_to_pay_as_an_integer",
	"customer": "the_customer_uuid",
	"description": "payment_description",
	"payment_method_details":{
		"pse":{
			"beneficiary_bank_account":"your_account_uuid", // The account that collects the payment
      		"belvo_flow": true,	// Optional field - This parameter set to true (default) creates the payment intent using the Belvo flow 
			"callback_url": "url_to_redirect_to_if_process_successful" // The callback URL that your user will be redirected to after confirming the payment in their banking application.
		}
	},
	"provider": "payments_way"
}

{
	"allowed_payment_method_types":["pse"],
	"amount": "350000",
	"customer": "c1b70f8f-b033-4891-bb38-167ea6a1c290",
	"description": "Awesome training Sneaker",
	"payment_method_details":{
		"pse":{
			"beneficiary_bank_account":"82582a40-2e75-42a5-b5e7-f593cfdbdf64",
      		"belvo_flow": true,
			"callback_url": "https://www.acmecorp.com/checkout/3487565/success"
		}
	},
	"provider": "payments_way"
}

📘

Additional info about amount and belvo_flow

amount
You can only send whole numbers (integers), meaning digits 0-9 with no decimals points. Otherwise, our API will return a 400 Invalid Error.

belvo_flow(optional)

You can set this parameter to false if you want to create a payment intent using the non-Belvo flow. Check our PSE Payment intents: inflow payments (non-Belvo flow) guide for more info. 🙂

You'll receive the following response containing instructions (in the next_step object) you’ll need to follow to guide your user through the payment flow. In this case, you’ll receive a pse_display_customer_bank_accounts instruction with a list of bank accounts that you need to display to your user for them to select from.

{
	"id": "e9cfd041-368c-404b-8a16-2a8db16a75b1",
	"allowed_payment_method_types":["pse"],
	"amount": "350000",
	"charges":[],
	"created_at":"2023-03-03T19:24:49.825406Z",
	"created_by":"cefab866-b96b-4a9f-b6e2-9857dec88ec8",
	"currency": "COP",
	"customer": "c1b70f8f-b033-4891-bb38-167ea6a1c290",
	"description": "Awesome training Sneaker",
	"failure_code": null,
	"failure_message": null,
	"metadata":{},
	"next_step":{   // This is the next step in the payment flow you need to follow.
		"type": "pse_display_customer_bank_accounts",
		"pse_display_customer_bank_accounts":{
			"beneficiary_bank_account":{
				"id": "82582a40-2e75-42a5-b5e7-f593cfdbdf64",
				"institution":null,
				"number":null,
				"holder":{
					"type":"BUSINESS",
					"information":{
						"name": "ACME Corp"
					}
				}
			},
			"customer_bank_accounts":[
				{
					"id":"f3a426c2-8d1d-422c-98af-bd293aa68855",
					"customer":"c1b70f8f-b033-4891-bb38-167ea6a1c290",
					"institution":{
						"id": "045dcbe4-fc39-4d70-8eec-0808821a371f",
						"active":true,
						"country":"COL",
						"display_name":"Erebor Bank",
						"form_fields":[
							{
								"name":"username",
								"type":"text",
								"label":"Usuario",
								"validation":"^(?=.*[0-9])(?=.*[a-zA-Z])([a-zA-Z0-9ñ]){8,20}$",
								"placeholder":"Usuario",
								"validation_message":"Requiere entre 8 y 20 dígitos, 1 número y 1 letra"
							},
							{
								"name":"password",
								"type":"password",
								"label":"Clave",
								"validation":"^\\d{4}$",
								"placeholder":"****",
								"validation_message":"Requiere 4 dígitos"
							},
							{
								"name":"token",
								"type":"number",
								"label":"Clave Dinámica",
								"length":6,
								"optional":false,
								"validation":"^\\d{6}$",
								"validation_message":"Requiere 6 dígitos"
							}
						],
						"icon_logo":"https://statics.belvo.io/institutions/icon_logos/ereborbank.svg",
						"logo":"https://statics.belvo.io/institutions/text_logos/ereborbank.svg",
						"name":"ereborbank",
						"primary_color":"#fdbc24",
						"text_logo":"https://statics.belvo.io/institutions/text_logos/ereborbank.svg",
						"website":"https://www.grupoereborcolombia.com"
					},
					"number": "******1234",// This value is masked.

					"holder":{
						"type":"INDIVIDUAL",
						"information":{
							"first_name":"Carlos",
							"last_name":"Vives"
						}
					},
					"details":{
						"country":"COL",
						"account_type": "Ahorros - Cuenta de Ahorro"
					}
				}
			]
		},
		"ready_to_confirm": false // When set to true, it means you can confirm the payment intent in the PATH request.
	},
	"last_error":{},
	"payment_method_details":{
		"pse":{
            "belvo_flow": true,
            "callback_url": "https://www.acmecorp.com/checkout/3487565/success",
            "beneficiary_bank_account":"82582a40-2e75-42a5-b5e7-f593cfdbdf64",
            "payer_institution":"045dcbe4-fc39-4d70-8eec-0808821a371f"
        }
	},
	"payment_method_information":{},
	"provider":"payments_way",
	"selected_payment_method_type":"pse",
	"status":"REQUIRES_PAYMENT_METHOD",
	"updated_at":"2023-03-03T19:56:21.235271Z"
}

👍

Tip!

Make sure to save the id you receive, as you’ll need it to complete the payment intent flow 🤓.

Complete a payment intent

Now that you've created the payment intent, you need to fill in with required information about your customer. To do so, you need to make PATCH Complete a payment intent requests. With each PATCH request, Belvo returns a next step that lets you know what information you need to send through next.

📘

Check our PSE Payments reference guide for more detailed info on next steps.

Selecting payer account

When Belvo returns pse_display_customer_bank_accounts next step, you'll need to display a list of bank accounts to your user for them to select. Once they’ve selected the bank account they want to pay with, you’ll need to send through that bank account in a PATCH Complete a payment intent request (as shown below).

{
	"payment_method_details": {
		"pse": {
			"payer_bank_account": "f3a426c2-8d1d-422c-98af-bd293aa68855"
		}
	}
}

You'll receive the following response containing instructions (in the next_step object) you’ll need to follow to guide your user through the payment flow. In this case, you’ll receive a pse_display_token_required instruction with information about the institution that you need to display to your user so they can send the MFA token required by the institution.

{
	"id":"e9cfd041-368c-404b-8a16-2a8db16a75b1",
...
	"next_step":{    // This is the next step in the payment flow you need to follow.
		"type": "pse_display_token_required",
		"pse_display_token_required":{
			"payer_institution":{
            "id":"045dcbe4-fc39-4d70-8eec-0808821a371f",
            "active":true,
            "country":"COL",
            "display_name":"Erebor Bank",
            "form_fields":[],
            "icon_logo":"https://statics.belvo.io/institutions/icon_logos/ereborbank.svg",
            "logo":"https://statics.belvo.io/institutions/text_logos/ereborbank.svg",
            "name":"ereborbank",
            "primary_color":"#fdbc24",
            "text_logo":"https://statics.belvo.io/institutions/text_logos/ereborbank.svg",
            "website":"https://www.grupoereborcolombia.com"
			}
		},
		"ready_to_confirm": true // When set to true, it means you can confirm the payment intent in the PATH request.
	},
	"last_error":{},
	"payment_method_details":{
		"pse":{
            "belvo_flow": true,
            "callback_url": "https://www.acmecorp.com/checkout/3487565/success", 	
			"payer_institution":"045dcbe4-fc39-4d70-8eec-0808821a371f",
			"beneficiary_bank_account":"82582a40-2e75-42a5-b5e7-f593cfdbdf64",
			"username":"***", // This value is masked.
			"password":"***" // This value is masked.
		}
	},
	"payment_method_information":{},
	"provider":"payments_way",
	"selected_payment_method_type":"pse",
	"status":"REQUIRES_PAYMENT_METHOD",
	"updated_at":"2023-03-03T19:48:56.360224Z"
}

📘

The response returns "ready_to_confirm": true, which means that the payment intent is ready to be processed. You can choose to send through the confirmation in the Sending the MFA token step or in a later request.

Sending the MFA token

When Belvo returns pse_display_token_required next step, you'll need to ask your customer to provide the MFA token required by the institution. Once they've sent the token, you'll need to send through the token in a PATCH Complete a payment intent request. Here you can choose whether you want to confirm the payment intent in this step or in a later request (as shown below).

{
	"payment_method_details": {
		"pse": {
			"payer_token": "123456"
		}
	},
 "confirm": true, // you'll process the payment by sending through this parameter set to true.
}
{
	"payment_method_details": {
		"pse": {
			"payer_bank_account": "f3a426c2-8d1d-422c-98af-bd293aa68855"
		}
	}
}

You'll receive the following response containing instructions (in the next_step object) you’ll need to follow to guide your user through the payment flow. Depending on whether you confirmed the payment intent or not in this step, you’ll receive a:

  • pse_display_payment_processing instruction to show that the payment is being processed.
  • pse_display_confirmation_required instruction to show that the payment is confirmed.
{
	"id":"e9cfd041-368c-404b-8a16-2a8db16a75b1",
...
	"next_step":{ // This is the next step in the payment flow you need to follow.
		"type":"pse_display_payment_processing",
		"pse_display_payment_processing":{
			"payer_institution":{
				"id":"045dcbe4-fc39-4d70-8eec-0808821a371f",
				"active":true,
				"country":"COL",
				"display_name":"Erebor Bank",
				"form_fields":[],
				"icon_logo":"https://statics.belvo.io/institutions/icon_logos/ereborbank.svg",
				"logo":"https://statics.belvo.io/institutions/text_logos/ereborbank.svg",
				"name":"ereborbank",
				"primary_color":"#fdbc24",
				"text_logo":"https://statics.belvo.io/institutions/text_logos/ereborbank.svg",
				"website":"https://www.grupoereborcolombia.com"
			}
		}
	},
	"last_error":{},
	"payment_method_details":{
		"pse":{
            "belvo_flow": true,
            "callback_url": "https://www.acmecorp.com/checkout/3487565/success", 
			"password":"***", // This value is masked.
			"username":"***", // This value is masked.
			"payer_token":"***", // This value is masked.
			"payer_institution":"045dcbe4-fc39-4d70-8eec-0808821a371f",
			"beneficiary_bank_account":"f3a426c2-8d1d-422c-98af-bd293aa68855",
			"payer_bank_account":"d170b8a6-7247-47d9-84e2-4d39da01f712"
		}
	},
	"payment_method_information":{
		"pse":{
			"redirect_url":"https://pse.com/Ereborbank/control/ElectronicPayment.ereborbank?PAYMENT_ID=456213985641233659874512459842",
			"provider_request_id":"eabae5ee-5a71-48a9-98be-dcc5449d8335",
			"bank_payment_id":"456213985641233659874512459842",
      		"end_to_end_id": "1237300520"
		}
	},
	"provider":"payments_way",
	"selected_payment_method_type":"pse",
	"status":"PROCESSING",
	"updated_at":"2023-03-04T02:12:11.059189Z"
}
{
	"id":"e9cfd041-368c-404b-8a16-2a8db16a75b1",
...
	"next_step":{ // This is the next step in the payment flow you need to follow.
		"type":"pse_display_confirmation_required",
		"pse_display_confirmation_required":{
			"payer_institution":{
				"id":"045dcbe4-fc39-4d70-8eec-0808821a371f",
				"active":true,
				"country":"COL",
				"display_name":"Erebor Bank",
				"form_fields":[],
				"icon_logo":"https://statics.belvo.io/institutions/icon_logos/ereborbank.svg",
				"logo":"https://statics.belvo.io/institutions/text_logos/ereborbank.svg",
				"name":"ereborbank",
				"primary_color":"#fdbc24",
				"text_logo":"https://statics.belvo.io/institutions/text_logos/ereborbank.svg",
				"website":"https://www.grupoereborcolombia.com"
			}
		},
		"ready_to_confirm": true // When set to true, it indicates the payment intent is ready to be processed in the next PATCH request.
	},
	"last_error":{},
	"payment_method_details":{
		"pse":{
            "belvo_flow": true,
            "callback_url": "https://www.acmecorp.com/checkout/3487565/success", 
			"password":"***", // This value is masked.
			"username":"***", // This value is masked.
			"payer_token":"***", // This value is masked.
			"payer_institution":"045dcbe4-fc39-4d70-8eec-0808821a371f",
			"beneficiary_bank_account":"f3a426c2-8d1d-422c-98af-bd293aa68855",
			"payer_bank_account":"d170b8a6-7247-47d9-84e2-4d39da01f712"
		}
	},
	"payment_method_information":{},
	"provider":"payments_way",
	"selected_payment_method_type":"pse",
	"status":"REQUIRES_PAYMENT_METHOD",
	"updated_at":"2023-03-03T19:57:04.227298Z"
}

📘

Webhooks notification

Belvo will send a payment intent status update webhook event to let you know the payment intent is now PROCESSING.

Check our Webhooks article for more info. 🤓

If something wrong happens when you send through your user's token, Belvo will return a different next step with instructions you’ll need to follow to guide your user back to the payment flow.

  • pse_display_token_required: the token provided by the customer is invalid and you need to ask them to send a token again.
  • pse_display_payment_method_information: there was an unexpected error during the payment process and the customer needs to start the payment flow from the beginning.

📘

Encountering last errors

If something doesn’t go well during the payment process, Belvo returns a last_error with information about what caused the error.

You can check our last encountered errors article for detailed info and possible solutions.

(Optional) Confirming the payment intent

If you didn't send the confirmation in the Sending the MFA token step, Belvo returns a pse_display_confirmation_required next step. This means that you'll need to send through the confirmation alone in a PATCH Complete a payment intent request (as shown below).

{
	"confirm": true
}

You'll receive the following response containing instructions (in the next_step object) you’ll need to follow to guide your user through the payment flow. In this case, you’ll receive a pse_display_confirmation_required instruction to show that the payment is confirmed.

{
	"id":"e9cfd041-368c-404b-8a16-2a8db16a75b1",
...
	"next_step":{ // This is the next step in the payment flow you need to follow.
		"type":"pse_display_payment_processing",
		"pse_display_payment_processing":{
			"payer_institution":{
				"id":"045dcbe4-fc39-4d70-8eec-0808821a371f",
				"active":true,
				"country":"COL",
				"display_name":"Erebor Bank",
				"form_fields":[],
				"icon_logo":"https://statics.belvo.io/institutions/icon_logos/ereborbank.svg",
				"logo":"https://statics.belvo.io/institutions/text_logos/ereborbank.svg",
				"name":"ereborbank",
				"primary_color":"#fdbc24",
				"text_logo":"https://statics.belvo.io/institutions/text_logos/ereborbank.svg",
				"website":"https://www.grupoereborcolombia.com"
			}
		}
	},
	"last_error":{},
	"payment_method_details":{
		"pse":{
            "belvo_flow": true,
            "callback_url": "https://www.acmecorp.com/checkout/3487565/success", 
			"password":"***", // This value is masked.
			"username":"***", // This value is masked.
			"payer_token":"***", // This value is masked.
			"payer_institution":"045dcbe4-fc39-4d70-8eec-0808821a371f",
			"beneficiary_bank_account":"f3a426c2-8d1d-422c-98af-bd293aa68855",
			"payer_bank_account":"d170b8a6-7247-47d9-84e2-4d39da01f712"
		}
	},
	"payment_method_information":{
		"pse":{
			"redirect_url":"https://pse.com/Ereborbank/control/ElectronicPayment.ereborbank?PAYMENT_ID=456213985641233659874512459842",
			"provider_request_id":"eabae5ee-5a71-48a9-98be-dcc5449d8335",
			"bank_payment_id":"456213985641233659874512459842",
      		"end_to_end_id": "1237300520"
		}
	},
	"provider":"payments_way",
	"selected_payment_method_type":"pse",
	"status":"PROCESSING",
	"updated_at":"2023-03-04T02:12:11.059189Z"
}

Done! 🎉 Once Belvo confirms that the payment has been processed and the money has been transferred to the beneficiary account, you'll receive:

  • a payment intent status update webhook event to inform you that the payment intent is now SUCCEEDED (or FAILED if something went wrong).
  • a new webhook called Transactions (object_created) to notify you that an actual transfer of funds from one account to another has occurred.

Check our Webhooks article for more info. 🤓

What's next? You can confirm the transfer of funds by checking the status of the payment intent and listening to the Transactions webhook.

How do you know that your payment has been completed?

Once the payment intent is processed, it’ll automatically change its status to SUCCEEDED or FAILED.

{
	"id":"e9cfd041-368c-404b-8a16-2a8db16a75b1",
...
	"next_step":{ // This is the next step in the payment flow you need to follow.
		"type":"pse_display_payment_succeeded",
		"pse_display_payment_succeeded":{
			"payer_name":"Carlos Vives",
			"payer_identifier":"1098712345",
			"payer_institution":{
				"id":"045dcbe4-fc39-4d70-8eec-0808821a371f",
				"logo":"https://statics.belvo.io/institutions/text_logos/ereborbank.svg",
				"name":"ereborbank",
				"active":true,
				"country":"COL",
				"website":"https://www.grupoereborcolombia.com",
				"icon_logo":"https://statics.belvo.io/institutions/icon_logos/ereborbank.svg",
				"text_logo":"https://statics.belvo.io/institutions/text_logos/ereborbank.svg",
				"form_fields":[],
				"display_name":"Erebor Bank",
				"primary_color":"#fdbc24"
			},
			"beneficiary_bank_account":{
				"id":"f3a426c2-8d1d-422c-98af-bd293aa68855",
				"holder":{
					"type":"BUSINESS",
					"information":{
						"name":"Acme Corp"
					}
				},
				"number":null,
				"institution":null
			}
		}
	},
	"last_error":{},
	"payment_method_details":{
		"pse":{
			"password":"***", // This value is masked.
			"username":"***", // This value is masked.
			"payer_token":"***", // This value is masked.
			"payer_institution":"045dcbe4-fc39-4d70-8eec-0808821a371f",
			"beneficiary_bank_account":"f3a426c2-8d1d-422c-98af-bd293aa68855",
			"payer_bank_account":"d170b8a6-7247-47d9-84e2-4d39da01f712",
      		"belvo_flow": true,
      		"callback_url": "https://www.acmecorp.com/checkout/3487565/success"
		}
	},
	"payment_method_information":{
		"pse":{
			"redirect_url":"https://pse.com/Ereborbank/control/ElectronicPayment.ereborbank?PAYMENT_ID=456213985641233659874512459842",
			"provider_request_id":"eabae5ee-5a71-48a9-98be-dcc5449d8335",
			"bank_payment_id":"456213985641233659874512459842",
      		"end_to_end_id": "1237300520"
		}
	},
	"provider":"payments_way",
	"selected_payment_method_type":"pse",
	"status":"SUCCEEDED",
	"updated_at":"2023-03-04T02:12:11.059189Z"
}
{
	"id":"e9cfd041-368c-404b-8a16-2a8db16a75b1",
...
	"failure_code": "expired",
	"failure_message": "This Payment Intent was marked as failed because its associated Payment Link was expired.",
	"next_step":{ // This is the next step in the payment flow you need to follow.
		"type":"pse_display_payment_failed",
		"pse_display_payment_failed":{
			"payer_institution":{
				"id":"045dcbe4-fc39-4d70-8eec-0808821a371f",
				"logo":"https://statics.belvo.io/institutions/text_logos/ereborbank.svg",
				"name":"ereborbank",
				"active":true,
				"country":"COL",
				"website":"https://www.grupoereborcolombia.com",
				"icon_logo":"https://statics.belvo.io/institutions/icon_logos/ereborbank.svg",
				"text_logo":"https://statics.belvo.io/institutions/text_logos/ereborbank.svg",
				"form_fields":[],
				"display_name":"Erebor Bank",
				"primary_color":"#fdbc24"
			}
		}
	},
	"last_error":{},
	"payment_method_details":{
		"pse":{
			"password":"***", // This value is masked.
			"username":"***", // This value is masked.
			"payer_token":"***", // This value is masked.
			"payer_institution":"045dcbe4-fc39-4d70-8eec-0808821a371f",
			"beneficiary_bank_account":"f3a426c2-8d1d-422c-98af-bd293aa68855",
			"payer_bank_account":"d170b8a6-7247-47d9-84e2-4d39da01f712",
      		"belvo_flow": true,
      		"callback_url": "https://www.acmecorp.com/checkout/3487565/success"
		}
	},
	"payment_method_information":{},
	"provider":"payments_way",
	"selected_payment_method_type":"pse",
	"status":"FAILED",
	"updated_at":"2022-12-22T21:17:23.566053Z"
},

We’ll also inform you of every successful payment by sending you a Transactions webhook - a payment transaction is an actual transfer of funds from one account to another 😉. This means that every time money has been successfully transferred to your account, you’ll receive the following notification:

{
  "webhook_id": "3b9a69f7-0f0a-455b-832d-49ad6fd4905c",
  "webhook_type": "TRANSACTIONS",
  "webhook_code": "OBJECT_CREATED",
  "object_id": "d2e40773-19f6-48d1-93c3-3590ec0c74df",
  "data": {}, //For OBJECT_CREATED webhooks, the data field returns an empty object.
}

You can also get details about a transaction by making a GET details request using the object_id of the transaction (which you receive in the webhook event).

{
  "id": "8828c442-eb79-404c-a813-ab3992c6d079",
  "created_at": "2023-03-04T02:13:30.775015Z",
  "created_by": "cefab866-b96b-4a9f-b6e2-9857dec88ec8",
  "amount": "350000",
  "currency": "COP",
  "description": "Awesome training Sneaker",
  "transaction_type": "INFLOW",
  "beneficiary": "f3a426c2-8d1d-422c-98af-bd293aa68855",
  "payer": {
    "bank_account": "d170b8a6-7247-47d9-84e2-4d39da01f712",
    "bank_account_information":{},
    "institution": "045dcbe4-fc39-4d70-8eec-0808821a371f"
  },
  "payment_intent": "e9cfd041-368c-404b-8a16-2a8db16a75b1",
  "customer": "c1b70f8f-b033-4891-bb38-167ea6a1c290"
}

👍

Need more info? Check out our API reference! 🤓

Summary

In this guide you learned how to:

  • create a payment intent
  • how to navigate the payment intent flow
  • confirm that a payment intent is successful

👍

If you have any questions, just reach out to us out to us and we’ll help you right away. 🙂