# Boleto payments

Learn how to accept Boleto, a common payment method in Brazil.

# Direct API


Stripe users in Brazil can accept Boleto payments from customers in Brazil by using the Payment Intents and Payment Methods APIs. *Customers* (Customer objects and some v2 Account objects represent customers of your business. They let you reuse payment methods and track multiple payments) pay by using a Boleto voucher with a generated number either in ATMs, banks, bank portals or authorized agencies.

## Set up Stripe [Server-side]

First, you need a Stripe account. [Register now](https://dashboard.stripe.com/register).

Use our official libraries for access to the Stripe API from your application:

#### Ruby

```bash
# Available as a gem
sudo gem install stripe
```

```ruby
# If you use bundler, you can add this line to your Gemfile
gem 'stripe'
```

## Create a PaymentIntent [Server-side]

Stripe uses a [PaymentIntent](https://docs.stripe.com/api/payment_intents.md) 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).

Included in the returned PaymentIntent is a *client secret* (The client secret is a unique key returned from Stripe as part of a PaymentIntent. This key lets the client access important fields from the PaymentIntent (status, amount, currency) while hiding sensitive ones (metadata, customer)), 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.

```curl
curl https://api.stripe.com/v1/payment_intents \
  -u "<<YOUR_SECRET_KEY>>:" \
  -d amount=1099 \
  -d currency=brl \
  -d "automatic_payment_methods[enabled]=true"
```

### Additional payment method options

You can specify an optional `expires_after_days` parameter in the [payment method options](https://docs.stripe.com/api/payment_intents/create.md#create_payment_intent-payment_method_options-boleto-expires_after_days) 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_after_days` 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_after_days` 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](https://dashboard.stripe.com/settings/payment_methods)

## Collect payment method details [Client-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_id`      | The CPF (for individuals) or CNPJ (for businesses) of the customer. The CPF must have 11 digits in either of the following formats: `000.000.000-00` or `00000000000`. The CNPJ must have 14 digits in either of the following formats: `00.000.000/0000-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](https://en.wikipedia.org/wiki/ISO_3166-2:BR)) of the customer’s address.                                                                                                                                                         |
| `postal_code` | Postal code of the customer’s address. The postal code must be in either of the following formats: `XXXXX-XXX` or `XXXXXXXX`.                                                                                                                                                     |

> These fields `name`, `address`, `city` must contain at least one alphanumeric character from the [Basic Latin (ASCII) Unicode Block](https://en.wikipedia.org/wiki/Basic_Latin_\(Unicode_block\)).

```html
<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 Stripe [Client-side]

When a customer clicks to pay with Boleto, use Stripe.js to submit the payment to Stripe. [Stripe.js](https://docs.stripe.com/payments/elements.md) 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.

```html
<head>
  <title>Checkout</title>
  <script src="https://js.stripe.com/endive/stripe.js"></script>
</head>
```

Create an instance of Stripe.js with the following JavaScript on your checkout page.

```javascript
// 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('<<YOUR_PUBLISHABLE_KEY>>');
```

Use [stripe.confirmBoletoPayment](https://docs.stripe.com/js/payment_intents/confirm_boleto_payment) and the [client secret](https://docs.stripe.com/api/payment_intents/object.md#payment_intent_object-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.

```javascript
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;
  }
});
```

> `stripe.confirmBoletoPayment` might take several seconds to complete. During that time, disable your form from being resubmitted and show a waiting indicator such as 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_action`. Check the status of a PaymentIntent in the [Dashboard](https://dashboard.stripe.com/test/payments) or by inspecting the status property on the object. If the Boleto voucher wasn’t 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](https://docs.stripe.com/api/events/types.md#event_types-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_voucher_url` in [payment_intent.next_action.boleto_display_details](https://docs.stripe.com/api/payment_intents/object.md#payment_intent_object-next_action-boleto_display_details-hosted_voucher_url).

### Optional: Customize your voucher 

Stripe allows customization of customer-facing UIs on the [Branding Settings](https://dashboard.stripe.com/account/branding) 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 events [Server-side]

Boleto payments are asynchronous, so funds aren’t immediately available. Customers might not pay for the Boleto voucher immediately after checking out.

Stripe sends a [payment_intent.succeeded](https://docs.stripe.com/api/events/types.md#event_types-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* (A configurable endpoint that executes when it receives certain event notifications from an event destination) 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 isn’t paid before 23:59 America/Sao_Paulo (UTC-3) on the expiration date, Stripe sends a [payment_intent.payment_failed](https://docs.stripe.com/api/events/types.md#event_types-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_intent.succeeded`      | The customer paid for the Boleto voucher before expiration.   | Fulfill the goods or services that the customer purchased.                                  |
| `payment_intent.payment_failed` | The customer didn’t 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* (A sandbox is an isolated test environment that allows you to test Stripe functionality in your account without affecting your live integration. Use sandboxes to safely experiment with new features and changes), set `payment_method.billing_details.email` to the following values when you call [stripe.confirmBoletoPayment](https://docs.stripe.com/js/payment_intents/confirm_boleto_payment) to test different scenarios.

| Email                                          | Description                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        |
| ---------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `{any_prefix}@{any_domain}`                    | Simulates a Boleto voucher which a customer pays after 3 minutes and the `payment_intent.succeeded` webhook arrives after about 3 minutes. In production, this webhook arrives 1 business day after a payment.

  Example: fulaninho@example.com                                                                                                                                                                                                                                                                                                                                                                                                   |
| `{any_prefix}succeed_immediately@{any_domain}` | Simulates a Boleto voucher which a customer pays immediately and the `payment_intent.succeeded` webhook arrives within several seconds. In production, this webhook arrives 1 business day after a payment.

  Example: succeed_immediately@example.com                                                                                                                                                                                                                                                                                                                                                                                            |
| `{any_prefix}expire_immediately@{any_domain}`  | Simulates a Boleto voucher which expires before a customer pays and the `payment_intent.payment_failed` webhook arrives within several seconds.

  The `expires_at` field in [next_action.boleto_display_details](https://docs.stripe.com/api/payment_intents/object.md#payment_intent_object-next_action-boleto_display_details-expires_at) is set to the current time regardless of what the `expires_after_days` parameter in [payment method options](https://docs.stripe.com/api/payment_intents/create.md#create_payment_intent-payment_method_options-boleto-expires_after_days) is set to.

  Example: expire_immediately@example.com      |
| `{any_prefix}expire_with_delay@{any_domain}`   | Simulates a Boleto voucher which expires before a customer pays and the `payment_intent.payment_failed` webhook arrives after about 3 minutes.

  The `expires_at` field in [next_action.boleto_display_details](https://docs.stripe.com/api/payment_intents/object.md#payment_intent_object-next_action-boleto_display_details-expires_at) is set to 3 minutes in the future regardless of what the `expires_after_days` parameter in [payment method options](https://docs.stripe.com/api/payment_intents/create.md#create_payment_intent-payment_method_options-boleto-expires_after_days) is set to.

  Example: expire_with_delay@example.com |
| `{any_prefix}fill_never@{any_domain}`          | Simulates a Boleto voucher which never succeeds; it expires according to the `expires_at` field in [next_action.boleto_display_details](https://docs.stripe.com/api/payment_intents/object.md#payment_intent_object-next_action-boleto_display_details-expires_at) per the provided parameters in the [payment method options](https://docs.stripe.com/api/payment_intents/create.md#create_payment_intent-payment_method_options-boleto-expires_after_days) and the `payment_intent.payment_failed` webhook arrives after that.

  Example: fill_never@example.com                                                                                |

| Tax ID                                            | Description                                                                       |
| ------------------------------------------------- | --------------------------------------------------------------------------------- |
| CPF `000.000.000-00`

  CNPJ `00.000.000/0000-00` | In a sandbox, set `tax_id` to these values, so they bypass the tax ID validation. |

## Optional: Build your own voucher page [Client-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’ll handle the next action to display the Boleto details to your customer.

```javascript
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](https://docs.stripe.com/api/payment_intents/object.md#payment_intent_object-next_action-boleto_display_details-number).                |
| Expiration date  | Display the boleto voucher expiration date. Locate the UNIX timestamp after which the Boleto voucher expires on the `PaymentIntent` at [next_action.boleto_display_details.expires_at](https://docs.stripe.com/api/payment_intents/object.md#payment_intent_object-next_action-boleto_display_details-expires_at).                              |
| Download the 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](https://docs.stripe.com/api/payment_intents/object.md#payment_intent_object-next_action-boleto_display_details-pdf). |

## Optional: Confirm Payment Intent server-side [Server-side]

We recommend relying on Stripe.js to *confirm* (Confirming an intent indicates that the customer intends to use the current or provided payment method. Upon confirmation, the intent attempts to initiate the portions of the flow that have real-world side effects) 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:

```curl
curl https://api.stripe.com/v1/payment_intents \
  -u "<<YOUR_SECRET_KEY>>:" \
  -d amount=1099 \
  -d currency=brl \
  -d confirm=true \
  -d "automatic_payment_methods[enabled]=true" \
  --data-urlencode "return_url=https://example.com/return" \
  -d "payment_method_data[type]=boleto" \
  -d "payment_method_data[billing_details][name]=João da Silva" \
  --data-urlencode "payment_method_data[billing_details][email]=joao@exemplo.com" \
  -d "payment_method_data[billing_details][address][line1]=1234 Av. Paulista" \
  -d "payment_method_data[billing_details][address][city]=São Paulo" \
  -d "payment_method_data[billing_details][address][state]=SP" \
  -d "payment_method_data[billing_details][address][postal_code]=01310-000" \
  -d "payment_method_data[billing_details][address][country]=BR" \
  -d "payment_method_data[boleto][tax_id]=000.000.000-00"
```

## Optional: Send payment instruction emails

You can enable Boleto payment instruction emails on the [Email Settings](https://dashboard.stripe.com/settings/emails) page in the Dashboard. When enabled, Stripe sends payment instruction emails upon PaymentIntent confirmation. The emails contain the Boleto number and a link to the Stripe hosted voucher page.

> In [sandboxes](https://docs.stripe.com/sandboxes.md), instruction emails are only sent to email addresses linked to the Stripe account.

## Expiration and cancellation

Boleto vouchers expire after the `expires_at` UNIX timestamp and a customer can’t pay a Boleto voucher after it has expired. Boleto vouchers can’t be canceled before expiration.

After a Boleto voucher expires, the PaymentIntent’s status changes to `requires_payment_method`. At this point, you can confirm the PaymentIntent with another payment method or cancel.

