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:
| Status | Meaning |
|---|---|
pending | The subscription has been created but is still being processed |
active | The subscription has already been successfully processed, and the next invoice is already scheduled |
canceled | The subscription has been terminated, either because all charge attempts failed, because the partner requested the cancellation, or because the customer/subject chose to cancel.* |
completed | All 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"
}
}
}
}'
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
| Parameter | Description | Type | Required |
|---|---|---|---|
subscription | Subscription data containing at least the following required values: | object | true |
value | Total amount to be charged. Only numbers with exponent size 2 are allowed. (e.g.: 12.34). | string | true |
currency | Defines the subscription currency in ISO 4217 format, currently the only accepted value is "BRL". | string | true |
frequency | Defines how often the subscription will be charged. Possible values are: day, week, month, quarter, semester, year. | string | true |
cycles | Number of cycles the subscription will have. For example, if the frequency is month and cycles is 12, the subscription will last for 12 months. | object | true |
trial_days | Defines a trial period before the first charge. After the trial period ends, future charges always respect the original subscription date. | object | false |
free_days | Defines a grace period before the first charge. After the grace period ends, future charges will occur on the date the first charge occurred. | object | false |
total_retry_attempts | Defines 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. | object | false |
description | A brief description of the subscription. | object | false |
to_bank_account_id | Partner internal or external international bank account ID | string | true |
subject_id | The ID of the person or company involved in this subscription. | string | true |
meta | Any metadata you want to add to the subscription to help you identify it later. | object | false |
from_card | object | true | |
from_card.card_number | The card number without spaces | string | true |
from_card.card_expiration_date | Card expiration date in MM/YYYY format | string | true |
from_card.card_brand | Card brand, such as visa, mastercard, or elo | string | true |
from_card.card_security_code | 3-digit card security code | string | true |
from_card.fullname | Cardholder's full name | string | true |
from_card.threeds | Data containing at least the following required values: | object | true |
from_card.threeds.softDescriptor | a 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. | string | false |
from_card.threeds.httpAcceptBrowserValue | Value of the Accept Header of the Customer's browser. | string | true |
from_card.threeds.httpBrowserLanguage | Customer's browser language according to https://www.techonthenet.com/js/language_tags.php | string | true |
from_card.threeds.httpBrowserJavaEnabled | If Java is enabled on customer browser. Options: true, false | string | true |
from_card.threeds.httpBrowserJavaScriptEnabled | If JavaScript is enabled on customer browser. Options: true, false | string | true |
from_card.threeds.httpBrowserColorDepth | Number of bits used to display images. | string | true |
from_card.threeds.httpBrowserScreenHeight | Height of the Customer's screen resolution. | string | true |
from_card.threeds.httpBrowserScreenWidth | Width of the Customer screen resolution. | string | true |
from_card.threeds.httpBrowserTimeDifference | Difference in minutes between GMT time and that of the Customer's browser. | string | true |
from_card.threeds.userAgentBrowserValue | The exact value of the User Agent Header. | string | true |
from_card.threeds.ipAddress | It is the IP address of the Customer's device. | string | true |
from_card.threeds.challengeWindowSize | The size of the challenge window displayed to the shopper. Options: fullPage, 250x400, 390x400, 500x600, 600x400. | string | true |
from_card.meta.df_reference_id | Session ID generated after the DDC is completed. | string | true |
from_card.meta.mcc | Dynamic 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, 7372 | string | true |
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"
}
}'
HTTP Request
POST /subscriptions/:id/threeds_challenge
Path Parameters
| Parameter | Description | Type | Required |
|---|---|---|---|
id | Subscription ID | string | true |
Body Parameters
| Parameter | Description | Type | Required |
|---|---|---|---|
credit_card | object | true | |
card_number | The card number without spaces | string | true |
card_expiration_date | Card expiration date in MM/YYYY format | string | true |
card_brand | Card brand, such as visa, mastercard, or elo | string | true |
card_security_code | 3-digit card security code | string | true |
fullname | Cardholder's full name | string | true |
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"
}
}'
HTTP Request
POST /subscriptions
Body Parameters
| Parameter | Description | Type | Required |
|---|---|---|---|
subscription | Subscription data containing at least the following required values: | object | true |
value | Total amount to be charged. Only numbers with exponent size 2 are allowed. (e.g.: 12.34) | string | true |
currency | Defines the subscription currency in ISO 4217 format, currently the only accepted value is BRL | string | true |
frequency | Defines 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 subscription | string | true |
cycles | Number of cycles the subscription will have. For example, if the frequency is month and the cycles is 12, the subscription will last for 12 months | object | true |
trial_days | Defines a trial period before the first charge. After the trial period ends, future charges always respect the original subscription date | object | false |
free_days | Defines a grace period before the first charge. After the grace period ends, future charges will occur on the date the first charge occurred | object | false |
total_retry_attempts | Defines 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 | object | false |
description | A brief description of the subscription | object | false |
to_bank_account_id | Partner internal or external international bank account ID | string | true |
from_bank_account_id | Your exclusive BRL bank account ID | string | true |
subject_id | The ID of the person or company involved in this subscription | string | true |
meta | Any metadata you want to add to the subscription to help you identify it later | object | false |
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.
HTTP Request
GET /subscriptions/:id
Path Parameters
| Parameter | Description | Type | Required |
|---|---|---|---|
id | Subscription ID | string | true |
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.
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"
}'
HTTP Request
PUT /subscriptions/:id/cancel
Path Parameters
| Parameter | Description | Type | Required |
|---|---|---|---|
id | Subscription ID | string | true |
Body Parameters
| Parameter | Description | Type | Required |
|---|---|---|---|
reason | Reason for cancellation | string | true |
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...."
HTTP Request
GET /subscriptions/invoices/:id
Path Parameters
| Parameter | Description | Type | Required |
|---|---|---|---|
id | Subscription ID | string | true |
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...."
HTTP Request
GET /subscriptions/invoices
Path Parameters
| Parameter | Description | Type | Required |
|---|---|---|---|
last_id | Last subscription UUID for pagination | string | false |
With this endpoint, you can retrieve a list of all your invoices.