Skip to main content

Subscriptions

Recurring payments are an automated billing model where a customer provides a single authorization for periodic charges to be applied to their credit card or bank account.

A subscription consists of multiple invoices, and each invoice can contain one or more charges. For example, a subscription with twelve monthly cycles generates one invoice per month. Each invoice is processed on its due date, with the first collection attempt automatically triggered at 6:00 a.m. UTC. This attempt creates a charge record that reflects whether the payment was successful or not.

When a successful charge is completed, the invoice is marked as paid. On the other hand, when the charge failed, the system will retry the payment based on the subscription frequency. For daily subscriptions, retries occur within a few hours of the failure. For weekly or longer frequencies, retries are scheduled once per day until either the payment succeeds or the maximum number of attempts is reached. Due to this process, a single invoice may include multiple charges, representing both failed attempts and a final successful payment.

Invoice dates strictly follow the subscription schedule. If a subscription is created on 01/01/2025 with a monthly frequency, charges will occur on the 1st of every month. If a month does not contain the scheduled day (for example, February 31st), the system automatically adjusts the invoice date to the last valid day of the month, in this case, 28/02/2025 or 29/02/2025 in leap years. From March 2025 onward, the invoice date reverts to the originally scheduled day (31/03/2025). This date-adjustment rule applies only to the frequencies month, quarter, semester, and year.

In addition to the standard charge schedule, subscriptions may also include a trial or free period before the first charge:

The trial_days field defines a trial period before the first charge, with an important distinction: once the trial period ends, all future charges align with the original subscription date. For example, if a subscription is created on 2025-01-01 with 7 trial days, the first charge will occur on 2025-01-08. Subsequent charges, however, will follow the original subscription schedule for a monthly frequency, that means 2025-02-01, 2025-03-01, and so on.

The free_days field defines an initial free period before the first charge, and unlike trial_days, it shifts the entire billing schedule forward. For example, if a subscription is created on 2025-01-01 with 7 free days, the first charge will occur on 2025-01-08, and all subsequent charges will follow this new date: 2025-02-08, 2025-03-08, etc.

Subscription Statuses

There are different statuses a subscription can have:

StatusMeaning
pendingThe subscription has been created but is still being processed
activeThe subscription has already been successfully processed, and the next invoice is already scheduled
canceledThe subscription has been terminated, either because all charge attempts failed, because the partner requested the cancellation, or because the customer/subject chose to cancel.*
completedAll cycles have been successfully paid and the subscription has ended.*

*These are final statuses.

Subscription with BRL Card

Basically, using the subscription with a card is very similar to the Credit card transactions Brazil and Credit card transactions Brazil - JWT for DDC sections.

Create a Subscription using credit/debit card

curl -X POST "https://api.facilitapay.com/api/v1/subscriptions" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9...." \
-d '{
"subscription": {
"cycles": 12,
"frequency": "month",
"value": "100",
"currency": "BRL",
"description": "some description",
"subject_id": "your subject_id",
"to_bank_account_id": "your to_bank_account_id",
"from_card": {
"card_type": "credit",
"card_number": "4000000000001000",
"card_expiration_date": "09/2029",
"card_security_code": "123",
"card_brand": "Visa",
"fullname": "Jose Silva",
"threeds": {
"softDescriptor": "Attrus",
"httpAcceptBrowserValue": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8",
"httpBrowserLanguage": "en-US",
"httpBrowserJavaEnabled": "false",
"httpBrowserJavaScriptEnabled": "true",
"httpBrowserColorDepth": "24",
"httpBrowserScreenHeight": "969",
"httpBrowserScreenWidth": "1250",
"httpBrowserTimeDifference": "240",
"userAgentBrowserValue": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/138.0.0.0 Safari/537.36",
"ipAddress": "127.0.0.1",
"challengeWindowSize": "250x400"
}
}
}
}'
{
"data": {
"canceled_at": null,
"canceled_by_payer": null,
"canceled_reason": null,
"completed_at": null,
"currency": "BRL",
"cycles": 12,
"description": "some description",
"free_days": 0,
"frequency": "month",
"from_bank_account_id": null,
"id": "899758d4-145a-4481-9791-d28b254373cc",
"inserted_at": "2025-09-01T15:47:20.803645",
"payer_bank_account_id": null,
"payer_card_id": "df5d14f1-39b9-498d-bc20-e09b97e09281",
"payment_method": "card",
"status": "active",
"subject_id": "b009558e-16b0-45dd-9bb7-7edea3d7a5cf",
"to_bank_account_id": "f29b519d-0b54-42b7-af09-6ad78f0a889a",
"total_retry_attempts": 0,
"trial_days": 0,
"updated_at": "2025-09-01T15:47:20.874607",
"value": "100"
}
}
warning

Common mistakes

Not sending the full credit card name

Solution: Please provide full credit card name

Card number with less than 13 characters

Solution: Please provide a valid credit card number

HTTP Request

POST /subscriptions

Body Parameters

ParameterDescriptionTypeRequired
subscriptionSubscription data containing at least the following required values:objecttrue
valueTotal amount to be charged. Only numbers with exponent size 2 are allowed. (e.g.: 12.34).stringtrue
currencyDefines the subscription currency in ISO 4217 format, currently the only accepted value is "BRL".stringtrue
frequencyDefines how often the subscription will be charged. Possible values are: day, week, month, quarter, semester, year.stringtrue
cyclesNumber of cycles the subscription will have. For example, if the frequency is month and cycles is 12, the subscription will last for 12 months.objecttrue
trial_daysDefines a trial period before the first charge. After the trial period ends, future charges always respect the original subscription date.objectfalse
free_daysDefines a grace period before the first charge. After the grace period ends, future charges will occur on the date the first charge occurred.objectfalse
total_retry_attemptsDefines how many retry attempts will be made if charges fail, except for the first invoice. The default value is zero and it can range from zero to three.objectfalse
descriptionA brief description of the subscription.objectfalse
to_bank_account_idPartner internal or external international bank account IDstringtrue
subject_idThe ID of the person or company involved in this subscription.stringtrue
metaAny metadata you want to add to the subscription to help you identify it later.objectfalse
from_cardobjecttrue
from_card.card_numberThe card number without spacesstringtrue
from_card.card_expiration_dateCard expiration date in MM/YYYY formatstringtrue
from_card.card_brandCard brand, such as visa, mastercard, or elostringtrue
from_card.card_security_code3-digit card security codestringtrue
from_card.fullnameCardholder's full namestringtrue
from_card.threedsData containing at least the following required values:objecttrue
from_card.threeds.softDescriptora short description of the merchant that will appear on the buyer's credit card statement. The first 13 characters will be appended to the string "Facilitapay*", e.g.: "Attrus*Airbnb". Any characters that exceed this limit will be truncated.stringfalse
from_card.threeds.httpAcceptBrowserValueValue of the Accept Header of the Customer's browser.stringtrue
from_card.threeds.httpBrowserLanguageCustomer's browser language according to https://www.techonthenet.com/js/language_tags.phpstringtrue
from_card.threeds.httpBrowserJavaEnabledIf Java is enabled on customer browser. Options: true, falsestringtrue
from_card.threeds.httpBrowserJavaScriptEnabledIf JavaScript is enabled on customer browser. Options: true, falsestringtrue
from_card.threeds.httpBrowserColorDepthNumber of bits used to display images.stringtrue
from_card.threeds.httpBrowserScreenHeightHeight of the Customer's screen resolution.stringtrue
from_card.threeds.httpBrowserScreenWidthWidth of the Customer screen resolution.stringtrue
from_card.threeds.httpBrowserTimeDifferenceDifference in minutes between GMT time and that of the Customer's browser.stringtrue
from_card.threeds.userAgentBrowserValueThe exact value of the User Agent Header.stringtrue
from_card.threeds.ipAddressIt is the IP address of the Customer's device.stringtrue
from_card.threeds.challengeWindowSizeThe size of the challenge window displayed to the shopper. Options: fullPage, 250x400, 390x400, 500x600, 600x400.stringtrue
from_card.meta.df_reference_idSession ID generated after the DDC is completed.stringtrue
from_card.meta.mccDynamic MCC. If you have multiple merchant category codes, the MCC lets you send a different merchant category code per subscription. Options: 8999, 5045, 4722, 8299, 5947, 5065, 7372stringtrue

Confirm 3DS for BRL Card Subscription

Confirming the 3DS for the subscription with a card is also very similar to the Credit card transactions Brazil and Credit card transactions Brazil - JWT for DDC sections.

curl -X POST "https://api.facilitapay.com/api/v1/subscriptions/:id/threeds_challenge" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9...." \
-d '{
"credit_card": {
"card_brand": "Visa",
"card_expiration_date": "09/2029",
"card_number": "4000000000001000",
"card_security_code": "123",
"fullname": "Jose Silva"
}
}'
200OK
{
"data": {
"canceled_at": null,
"canceled_by_payer": null,
"canceled_reason": null,
"completed_at": null,
"currency": "BRL",
"cycles": 12,
"description": "some description",
"free_days": 0,
"frequency": "month",
"from_bank_account_id": null,
"id": "86c142b7-9b94-413d-9894-74c35835f666",
"inserted_at": "2025-09-12T21:00:54.680247",
"payer_bank_account_id": null,
"payer_card_id": "2241cdcd-bc2c-4361-8079-435b322e6f1f",
"payment_method": "card",
"status": "active",
"subject_id": "2c90ad60-31de-4624-a852-60960a814e2c",
"to_bank_account_id": "504fc315-ce61-4179-b19a-e4617eaae30f",
"total_retry_attempts": 0,
"trial_days": 0,
"updated_at": "2025-09-12T21:00:54.783049",
"value": "100"
}
}

HTTP Request

POST /subscriptions/:id/threeds_challenge

Path Parameters

ParameterDescriptionTypeRequired
idSubscription IDstringtrue

Body Parameters

ParameterDescriptionTypeRequired
credit_cardobjecttrue
card_numberThe card number without spacesstringtrue
card_expiration_dateCard expiration date in MM/YYYY formatstringtrue
card_brandCard brand, such as visa, mastercard, or elostringtrue
card_security_code3-digit card security codestringtrue
fullnameCardholder's full namestringtrue

Subscription with BRL Automatic PIX

BRL Automatic PIX subscriptions allow you to charge customers automatically through direct bank debits, providing a seamless recurring payment experience.

To create an automatic PIX subscription, send a POST request with the required payload. The system will return a subscription in "pending" status and generate a dynamic QR Code asynchronously for customer authorization.

Once generated, the QR Code will be included in the from_pix field of the subscription response, containing all payment details required for authorization. A webhook notification will also be sent to your endpoint to confirm that the QR Code is ready.

The customer must scan this QR Code using their bank's mobile app to authorize the automatic debit. This one-time authorization is mandatory — the subscription will only become active after the customer successfully completes the payment from their account.

After activation, charges will occur automatically based on the defined frequency, amount, and cycle limits. Customers can view upcoming debit transactions in their banking app up to two days before each settlement date.

If a payment fails due to insufficient funds, the system will retry according to your configured retry attempts. Each retry is scheduled every other day: for example, if a charge fails on the settlement date, the next debit attempt will be scheduled two days later. If that attempt also fails, another will be scheduled two days after, and so on, until the maximum number of retry attempts is reached. Once all retries are exhausted, the subscription will be canceled automatically, and a webhook notification will be sent to you.

Create a Subscription using automatic pix

curl -X POST "https://api.facilitapay.com/api/v1/subscriptions" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9...." \
-d '{
"subscription": {
"cycles": 12,
"frequency": "month",
"value": "100",
"currency": "BRL",
"description": "some description",
"subject_id": "your subject_id",
"to_bank_account_id": "your internal bank account id",
"from_bank_account_id": "your exclusive BRL bank account id"
}
}'
{
"data": {
"canceled_at": null,
"canceled_by_payer": null,
"canceled_reason": null,
"completed_at": null,
"currency": "BRL",
"cycles": 12,
"description": "some description",
"free_days": 0,
"frequency": "month",
"from_bank_account_id": "f29b519d-0b54-42b7-af09-6ad78f0a889a",
"from_pix": {
"qr_code": "00020126580014br.gov.bcb.pix0136123e4567-e89b-12d3-a456-426614174000520400005303986540510.005802BR5913FACILITA PAY6008BRASILIA62070503***63041D3D"
},
"id": "899758d4-145a-4481-9791-d28b254373cc",
"inserted_at": "2025-09-01T15:47:20.803645",
"payer_bank_account_id": null,
"payer_card_id": null,
"payment_method": "pix",
"status": "pending",
"subject_id": "b009558e-16b0-45dd-9bb7-7edea3d7a5cf",
"to_bank_account_id": "f29b519d-0b54-42b7-af09-6ad78f0a889a",
"total_retry_attempts": 0,
"trial_days": 0,
"updated_at": "2025-09-01T15:47:20.874607",
"value": "100"
}
}

HTTP Request

POST /subscriptions

Body Parameters

ParameterDescriptionTypeRequired
subscriptionSubscription data containing at least the following required values:objecttrue
valueTotal amount to be charged. Only numbers with exponent size 2 are allowed. (e.g.: 12.34)stringtrue
currencyDefines the subscription currency in ISO 4217 format, currently the only accepted value is BRLstringtrue
frequencyDefines how often the subscription will be charged. Possible values are: week, month, quarter, semester, year. Note that day is not allowed for this type of subscriptionstringtrue
cyclesNumber of cycles the subscription will have. For example, if the frequency is month and the cycles is 12, the subscription will last for 12 monthsobjecttrue
trial_daysDefines a trial period before the first charge. After the trial period ends, future charges always respect the original subscription dateobjectfalse
free_daysDefines a grace period before the first charge. After the grace period ends, future charges will occur on the date the first charge occurredobjectfalse
total_retry_attemptsDefines how many retry attempts will be made if charges fail, except for the first invoice. The default value is zero and it can range from zero to threeobjectfalse
descriptionA brief description of the subscriptionobjectfalse
to_bank_account_idPartner internal or external international bank account IDstringtrue
from_bank_account_idYour exclusive BRL bank account IDstringtrue
subject_idThe ID of the person or company involved in this subscriptionstringtrue
metaAny metadata you want to add to the subscription to help you identify it laterobjectfalse

Common Mistakes

You did not provide a valid source account ID in from_bank_account_id

Solution: You must provide the ID of your exclusive BRL bank account that we sent to you when we created your account. You can find it in the "Bank Accounts" page by logging in our portal and going to the "Attrus pay-in accounts" section.

Subscription remains in pending status for too long

Solution: Check if the customer has paid the QR Code. The pending status indicates that the QR Code was generated but not yet paid. The customer must scan the QR Code with their bank app and make the payment to activate the subscription.

Error generating dynamic QR Code

Solution: This error indicates a temporary issue with the QR Code generation service. Try again in a few minutes. If the problem persists, contact support.

Subscription automatically canceled

Solution: The subscription was canceled because the customer did not have sufficient funds on the settlement day and the maximum number of retry attempts was reached. You can create a new subscription or contact the customer to resolve payment issues.

Webhook not received

Solution: Verify that your webhook endpoint is properly configured and publicly accessible. Make sure it returns HTTP 200 status for notifications. Test your endpoint with tools like ngrok for local development.

Subscription Details

curl -X GET "https://api.facilitapay.com/api/v1/subscriptions/86c142b7-9b94-413d-9894-74c35835f666" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9...."

With this endpoint, you can retrieve detailed information about a specific subscription by providing its unique ID.

200OK
{
"data": {
"canceled_at": null,
"canceled_by_payer": null,
"canceled_reason": null,
"completed_at": null,
"currency": "BRL",
"cycles": 12,
"description": "some description",
"free_days": 0,
"frequency": "month",
"from_bank_account_id": null,
"id": "86c142b7-9b94-413d-9894-74c35835f666",
"inserted_at": "2025-09-12T21:00:54.680247",
"payer_bank_account_id": null,
"payer_card_id": "2241cdcd-bc2c-4361-8079-435b322e6f1f",
"payment_method": "card",
"status": "active",
"subject_id": "2c90ad60-31de-4624-a852-60960a814e2c",
"to_bank_account_id": "504fc315-ce61-4179-b19a-e4617eaae30f",
"total_retry_attempts": 0,
"trial_days": 0,
"updated_at": "2025-09-12T21:00:54.783049",
"value": "100"
}
}

HTTP Request

GET /subscriptions/:id

Path Parameters

ParameterDescriptionTypeRequired
idSubscription IDstringtrue

List Subscriptions

curl -X GET "https://api.facilitapay.com/api/v1/subscriptions" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9...."

With this endpoint, you can retrieve a list of all your subscriptions.

200OK
{
"data": [
{
"canceled_at": null,
"canceled_by_payer": null,
"canceled_reason": null,
"completed_at": null,
"currency": "BRL",
"cycles": 12,
"description": "some description",
"free_days": 0,
"frequency": "month",
"from_bank_account_id": null,
"id": "187acdc6-f512-4046-8d44-704b9f353c6f",
"inserted_at": "2025-09-19T15:02:25.261646",
"payer_bank_account_id": null,
"payer_card_id": "927302a6-de65-4268-aac1-2667c6ceb1c2",
"payment_method": "card",
"status": "active",
"subject_id": "56c419c6-c045-4ca4-a83b-204c09336892",
"to_bank_account_id": "7b1e792f-efec-48a8-a2b4-430b0fea286f",
"total_retry_attempts": 0,
"trial_days": 0,
"updated_at": "2025-09-19T15:02:25.287880",
"value": "100"
},
{
"canceled_at": null,
"canceled_by_payer": null,
"canceled_reason": null,
"completed_at": null,
"currency": "BRL",
"cycles": 12,
"description": "some description",
"free_days": 0,
"frequency": "month",
"from_bank_account_id": null,
"id": "6b0c55e3-740a-4999-9407-b387be8499c2",
"inserted_at": "2025-09-19T15:02:25.160250",
"payer_bank_account_id": null,
"payer_card_id": "df959a52-3611-409b-921d-472dddb67853",
"payment_method": "card",
"status": "active",
"subject_id": "56c419c6-c045-4ca4-a83b-204c09336892",
"to_bank_account_id": "7b1e792f-efec-48a8-a2b4-430b0fea286f",
"total_retry_attempts": 0,
"trial_days": 0,
"updated_at": "2025-09-19T15:02:25.249591",
"value": "100"
}
]
}

HTTP Request

GET /subscriptions

Cancel a Subscription

With this endpoint, you can cancel an active subscription by providing its unique ID. Once canceled, the subscription will no longer generate future invoices or charges.

curl -X PUT "https://api.facilitapay.com/api/v1/subscriptions/:id/cancel" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9...." \
-d '{
"reason": "some reason"
}'
200OK
{
"data": {
"canceled_at": "2025-09-17T14:50:41.026777Z",
"canceled_by_payer": false,
"canceled_reason": "some reason",
"completed_at": null,
"currency": "BRL",
"cycles": 12,
"description": "some description",
"free_days": 0,
"frequency": "month",
"from_bank_account_id": null,
"id": "3b6f32b7-ba43-4038-8c0b-3078069754d9",
"inserted_at": "2025-09-19T14:50:40.919497",
"payer_bank_account_id": null,
"payer_card_id": "c4aaddcd-875c-4cd0-993a-098da28baa4d",
"payment_method": "card",
"status": "canceled",
"subject_id": "f7f25961-4e68-473c-9579-67c529307835",
"to_bank_account_id": "7055d7b0-9126-4a9a-b5d8-290de368f1a5",
"total_retry_attempts": 0,
"trial_days": 0,
"updated_at": "2025-09-19T14:50:41.026830",
"value": "100"
}
}

HTTP Request

PUT /subscriptions/:id/cancel

Path Parameters

ParameterDescriptionTypeRequired
idSubscription IDstringtrue

Body Parameters

ParameterDescriptionTypeRequired
reasonReason for cancellationstringtrue

List Subscription Invoices

With this endpoint, you can retrieve a list of all invoices associated with a specific subscription by providing its unique ID.

curl -X GET "https://api.facilitapay.com/api/v1/subscriptions/invoices" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9...."
200OK
{
"data": [
{
"charge_at": "2025-10-19",
"cycle_number": 2,
"due_at": "2025-10-19",
"first_charge": false,
"id": "3799a7a0-392f-4368-80e7-1545cff0509d",
"inserted_at": "2025-09-19T16:26:13.989090",
"paid_at": null,
"retry_attempts": 0,
"status": "pending",
"transaction_id": null,
"updated_at": "2025-09-19T16:26:13.989095",
"value": "100"
},
{
"charge_at": "2025-09-19",
"cycle_number": 1,
"due_at": "2025-09-19",
"first_charge": true,
"id": "016685f9-3913-4f32-8963-8b6625ead91a",
"inserted_at": "2025-09-19T16:26:13.928480",
"paid_at": "2025-09-19T16:26:13.986621Z",
"retry_attempts": 0,
"status": "paid",
"transaction_id": "33b29f54-96cc-49cf-82bc-d77d443f261b",
"updated_at": "2025-09-19T16:26:13.986692",
"value": "100"
}
]
}

HTTP Request

GET /subscriptions/invoices/:id

Path Parameters

ParameterDescriptionTypeRequired
idSubscription IDstringtrue

Get invoice by id

Get the invoice by your id.

Request

curl -X GET "https://api.facilitapay.com/api/v1/subscriptions/invoices/:id" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9...."
200OK
{
"value": "1.12",
"updated_at": "2025-12-18T11:22:47.783935",
"transaction_id": "da3cd48e-dcec-47ea-bb04-b6b88870d638",
"status": "paid",
"retry_attempts": 0,
"paid_at": "2025-12-18T11:22:47.783896Z",
"inserted_at": "2025-12-17T12:05:10.490904",
"id": "681ebd10-5619-4c6a-a036-ae195c8e8115",
"first_charge": false,
"due_at": "2025-12-18",
"cycle_number": 3,
"charge_at": "2025-12-18"
}

HTTP Request

GET /subscriptions/invoices

Path Parameters

ParameterDescriptionTypeRequired
last_idLast subscription UUID for paginationstringfalse

With this endpoint, you can retrieve a list of all your invoices.

200OK
{
"data": [
{
"value": "1.12",
"updated_at": "2025-12-18T11:22:47.783935",
"transaction_id": "da3cd48e-dcec-47ea-bb04-b6b88870d638",
"status": "paid",
"retry_attempts": 0,
"paid_at": "2025-12-18T11:22:47.783896Z",
"inserted_at": "2025-12-17T12:05:10.490904",
"id": "681ebd10-5619-4c6a-a036-ae195c8e8115",
"first_charge": false,
"due_at": "2025-12-18",
"cycle_number": 1,
"charge_at": "2025-12-18"
},
{
"value": "1.12",
"updated_at": "2026-01-18T11:22:47.783935",
"transaction_id": "da3cd48e-dcec-47ea-bb04-b6b88870d638",
"status": "pending",
"retry_attempts": 0,
"paid_at": "2026-01-18T11:22:47.783896Z",
"inserted_at": "2026-01-17T12:05:10.490904",
"id": "681ebd10-5619-4c6a-a036-ae195c8e8115",
"first_charge": false,
"due_at": "2026-01-18",
"cycle_number": 2,
"charge_at": "2026-01-18"
}
]
}