Boleto payments
Learn how to accept Boleto, a common payment method in Brazil.
Stripe users in Brazil can accept Boleto payments from customers in Brazil by using the Payment Intents and Payment Methods APIs. Customers pay by using a Boleto voucher with a generated number either in ATMs, banks, bank portals or authorized agencies.
Set up StripeServer-side
First, you need a Stripe account. Register now.
Use our official libraries for access to the Stripe API from your application:
Create a PaymentIntentServer-side
Stripe uses a PaymentIntent object to represent your intent to collect payment from a customer, tracking state changes from Boleto voucher creation to payment completion.
Create a PaymentIntent on your server with an amount and the brl currency (Boleto doesn’t support other currencies). If you already have an integration using the Payment Intents API, add boleto to the list of payment method types for your PaymentIntent.
Included in the returned PaymentIntent is a client secret, which you have to use to securely complete the payment process. Send the client secret back to the client so you can use it in later steps.
Additional payment method options
You can specify an optional expires_ parameter in the payment method options for your PaymentIntent that sets the number of calendar days before a Boleto voucher expires. For example, if you create a Boleto voucher on Monday and you set expires_ to 2, the Boleto voucher will expire on Wednesday at 23:59 America/Sao_Paulo (UTC-3) time. If you set it to 0, the Boleto voucher will expire at the end of the day. The expires_ parameter can be set from 0 to 60 days. The default is 3 days. You can customize the default expiration days on your account in the Payment methods settings
Collect payment method detailsClient-side
Create a payment form on your client to collect the required billing details from the customer:
| Field | Value |
|---|---|
name | The full name of the customer. |
email | The email address of the customer. |
tax_ | The CPF (for individuals) or CNPJ (for businesses) of the customer. The CPF must have 11 digits in either of the following formats: 000. or 00000000000. The CNPJ must have 14 digits in either of the following formats: 00. or 00000000000000. |
address | Street name and number of the customer’s address. |
city | City of the customer’s address. |
state | Two-letter Brazilian state code (ISO_3166-2:BR) of the customer’s address. |
postal_ | Postal code of the customer’s address. The postal code must be in either of the following formats: XXXXX-XXX or XXXXXXXX. |
Note
These fields name, address, city must contain at least one alphanumeric character from the Basic Latin (ASCII) Unicode Block.
<form id="payment-form"> <div class="form-row"> <label for="name"> Name </label> <input id="name" name="name" required> </div> <div class="form-row"> <label for="tax_id"> CPF/CNPJ </label> <input id="tax_id" name="tax_id" required> </div> <div class="form-row"> <label for="email"> Email </label> <input id="email" name="email" required> </div> <div class="form-row"> <label for="address"> Address </label> <input id="address" name="address" required> </div> <div class="form-row"> <label for="city"> City </label> <input id="city" name="city" required> </div> <div class="form-row"> <label for="state"> State </label> <input id="state" name="state" required> </div> <div class="form-row"> <label for="postal_code"> Postal Code </label> <input id="postal_code" name="postal_code" required> </div> <!-- Used to display form errors. --> <div id="error-message" role="alert"></div> <button id="submit-button">Pay with Boleto</button> </form>
Submit the payment to StripeClient-side
When a customer clicks to pay with Boleto, use Stripe.js to submit the payment to Stripe. Stripe.js is our foundational JavaScript library for building payment flows.
Include the Stripe.js script on your checkout page by adding it to the head of your HTML file.
<head> <title>Checkout</title> <script src="https://js.stripe.com/clover/stripe.js"></script> </head>
Create an instance of Stripe.js with the following JavaScript on your checkout page.
// Set your publishable key. Remember to switch to your live publishable key in production! // See your keys here: https://dashboard.stripe.com/apikeys const stripe = Stripe();'pk_test_TYooMQauvdEDq54NiTphI7jx'
Use stripe.confirmBoletoPayment and the client secret of the PaymentIntent object that you created in Step 2 to submit the customer’s billing details.
Upon confirmation, Stripe will automatically open a modal to display the Boleto voucher to your customer.
var form = document.getElementById('payment-form'); form.addEventListener('submit', async (event) => { event.preventDefault(); const result = await stripe.confirmBoletoPayment( '{{PAYMENT_INTENT_CLIENT_SECRET}}', { payment_method: { boleto: { tax_id: document.getElementById('tax_id').value, }, billing_details: { name: document.getElementById('name').value, email: document.getElementById('email').value, address: { line1: document.getElementById('address').value, city: document.getElementById('city').value, state: document.getElementById('state').value, postal_code: document.getElementById('postal_code').value, country: 'BR', }, }, }, } ); // Stripe.js will open a modal to display the Boleto voucher to your customer // This async function finishes when the customer closes the modal if (result.error) { // Display error to your customer const errorMsg = document.getElementById('error-message'); errorMsg.innerText = result.error.message; } });
Note
stripe. may take several seconds to complete. During that time, disable your form from being resubmitted and show a waiting indicator like a spinner. If you receive an error, show it to the customer, re-enable the form, and hide the waiting indicator.
When a Boleto voucher is created successfully, the value of the returned PaymentIntent’s status property is requires_. Check the status of a PaymentIntent in the Dashboard or by inspecting the status property on the object. If the Boleto voucher was not created successfully, inspect the returned error to determine the cause (for example, invalid email format).
Optional: Email voucher link to your customer
Stripe sends a payment_intent.requires_action event when a Boleto voucher is created successfully. If you need to email your customers the voucher link, you can locate the hosted_ in payment_intent.next_action.boleto_display_details.
Optional: Customize your voucher
Stripe allows customization of customer-facing UIs on the Branding Settings page.
The following brand settings can be applied to the voucher:
- Icon—your brand image and public business name
- Accent color—used as the color of the Copy Number button
- Brand color—used as the background color
Handle post-payment eventsServer-side
Boleto payments are asynchronous, so funds are not immediately available. Customers might not pay for the Boleto voucher immediately after checking out.
Stripe sends a payment_intent.succeeded event on the next business day (Monday through Friday excluding Brazilian holidays) for each Boleto voucher that was paid. Use the Dashboard or a custom webhook to receive these events and run actions (for example, sending an order confirmation email to your customer, logging the sale in a database, or starting a shipping workflow).
If a Boleto voucher is not paid before 23:59 America/Sao_Paulo (UTC-3) on the expiry date, Stripe sends a payment_intent.payment_failed event after 1 business day. For example, if a Boleto voucher expires on Thursday, the event is sent on Friday. If a Boleto voucher expires on Friday, the event is sent the following Monday.
| Event | Description | Next steps |
|---|---|---|
payment_ | The customer paid for the Boleto voucher before expiration. | Fulfill the goods or services that the customer purchased. |
payment_ | The customer did not pay the Boleto voucher before expiration. | Contact the customer through email or push notification and request another payment method. |
Test the integration
In a sandbox, set payment_ to the following values when you call stripe.confirmBoletoPayment to test different scenarios.
| Description | |
|---|---|
| Simulates a Boleto voucher which a customer pays after 3 minutes and the Example: fulaninho@example.com |
| Simulates a Boleto voucher which a customer pays immediately and the Example: succeed_immediately@example.com |
| Simulates a Boleto voucher which expires before a customer pays and the The Example: expire_immediately@example.com |
| Simulates a Boleto voucher which expires before a customer pays and the The Example: expire_with_delay@example.com |
| Simulates a Boleto voucher which never succeeds; it expires according to the Example: fill_never@example.com |
| Tax ID | Description |
|---|---|
CPF CNPJ | In a sandbox, set |
OptionalBuild your own voucher pageClient-side
We recommend relying on Stripe.js to handle displaying the Boleto voucher with confirmBoletoPayment. However, you can also manually display the voucher to your customers.
You can specify handleActions: false when calling stripe.confirmBoletoPayment in step 4 to indicate that you will handle the next action to display the Boleto details to your customer.
var form = document.getElementById('payment-form'); form.addEventListener('submit', async (event) => { event.preventDefault(); const result = await stripe.confirmBoletoPayment( '{{PAYMENT_INTENT_CLIENT_SECRET}}', { payment_method: { boleto: { tax_id: document.getElementById('tax_id').value, }, billing_details: { name: document.getElementById('name').value, email: document.getElementById('email').value, address: { line1: document.getElementById('address').value, city: document.getElementById('city').value, state: document.getElementById('state').value, postal_code: document.getElementById('postal_code').value, country: 'BR', }, }, }, }, {handleActions: false}, ); if (result.error) { // Display error to your customer const errorMsg = document.getElementById('error-message'); errorMsg.innerText = result.error.message; } else { // An Boleto voucher was successfully created const amount = result.paymentIntent.amount; const currency = result.paymentIntent.currency; const details = result.paymentIntent.next_action.boleto_display_details; const number = details.number; const expires_at = details.expires_at; // Handle the next action by displaying the Boleto details to your customer // You can also use the generated hosted voucher const hosted_voucher_url = details.hosted_voucher_url; } });
Include, at minimum, the following:
| Detail | Description |
|---|---|
| Number | Display the boleto voucher number such that it’s easy for your customers to copy them to their clipboard. Locate the number on the PaymentIntent object at next_action.boleto_display_details.number. |
| Expiry date | Display the boleto voucher expiry date is. Locate the UNIX timestamp after which the Boleto voucher expires on the PaymentIntent at next_action.boleto_display_details.expires_at. |
| Download pdf | Display a download button that allows your customer to download the boleto pdf. Locate the pdf, where the customer can download the Boleto voucher PDF, on the PaymentIntent at next_action.boleto_display_details.pdf. |
OptionalConfirm Payment Intent server-sideServer-side
We recommend relying on Stripe.js to confirm a Boleto Payment Intent with confirmBoletoPayment. Using Stripe.js makes it much easier to extend your integration to other payment methods. However, you can also confirm a Payment Intent server-side as follows:
OptionalSend payment instruction emails
You can enable Boleto payment instruction emails on the Email Settings page in the Dashboard. Once enabled, Stripe sends payment instruction emails upon PaymentIntent confirmation. The emails contain the Boleto number and a link to the Stripe hosted voucher page.
Note
In test environments, instruction emails are only sent to email addresses linked to the Stripe account.
Expiration and cancellation
Boleto vouchers expire after the expires_ UNIX timestamp and a customer can’t pay a Boleto voucher once it has expired. Boleto vouchers can’t be canceled before expiration.
After a Boleto voucher expires, the PaymentIntent’s status changes to requires_. At this point, you can confirm the PaymentIntent with another payment method or cancel.