Recurring Payment Schedule
Once your enrollment is accepted, you can schedule recurring payments according to the cycle you have configured(through frequency and start_date).
Pix Automático operates on a schedule-based approach. The Central Bank of Brazil requires that payment requests be made between 2 and 10 days before the expected billing date, ensuring customers have sufficient visibility of upcoming charges.
For example, if a payment is due on January 12th, the payment request must be sent no earlier than January 2nd and no later than January 10th.
At every cycle, you must repeat the process described below to ensure your charges are processed on time.
Requirements
- EBANX Sandbox Account - Provides a test environment where you can explore our payment solutions.
- Sign up for an EBANX Sandbox Account.
- Complete the online form.
- Our team will reach out to you shortly.
- API authentication - All API requests must be authenticated using JWS (JSON Web Signature). The legacy
integration_keyis being deprecated — if you still use it, follow the Migration Guide to transition to JWS. If you don't have credentials yet, complete the Merchant Signup Form. - Familiarity with EBANX Direct - This setup follows the same general structure as other payment methods, with a few unique parameters. See EBANX Direct for more info.
Instructions
To schedule a Pix Automático recurring payment, follow the steps below.
- Schedule the Pix Automático paymentImportant!
The recurring payment request must be sent between 2 and 10 days prior to the next billing date.
For instance, if the payment is due on January 17th, the request must be submitted between January 7th and January 15th.Scheduling a recurring payment with Pix Automático is really straightforward. The following fields will be required:
Parameter Requirement Description merchant_payment_codeRequired Unique merchant payment code amount_totalRequired Total amount to be charged. Note that the amount must match the one set in the enrollment currency_codeRequired Must be BRLcountryRequired Must be BRpayment_type_codeRequired Must be pix-automaticoemailRequired Customer e-mail nameRequired Customer name documentRequired Customer document due_dateRequired Expected billing date (DD/MM/YYYY) - it must be between 2 and 10 days after the current date merchant_enrollment_codeRequired The enrollment code generated in the previous steps. The enrollment must have a acceptedstatus to be used in recurring paymentsCheck the example:
Shellcurl -X POST \
--location 'https://sandbox.ebanxpay.com/ws/direct' \
--header 'Content-Type: application/json' \
--data '{
"integration_key": "{{integration_key}}",
"payment": {
"merchant_payment_code": "{{unique_merchant_code}}",
"amount_total": 99.85,
"currency_code": "BRL",
"country": "BR",
"payment_type_code": "pix-automatico",
"email": "john.doe@example.com",
"name": "John Doe",
"document": "{{tax_id}}",
"due_date": "{{DD/MM/YYYY}}",
"enrollment": {
"merchant_enrollment_code": "{{unique_enrollment_code}}"
}
}
}'A successful request will return a JSON response like the one below. The Pix Automático payment will have a pending (
PE) status and will be confirmed later by the customer's bank.JSON{
"payment": {
"hash": "59acc5f00945fa382ab051651440826da7701533249b3a475",
"country": "BR",
"merchant_payment_code": "{{unique_merchant_code}}",
"status": "PE",
"status_date": "{{YYYY-MM-DD HH:mm:ss}}",
"open_date": "{{YYYY-MM-DD HH:mm:ss}}",
"confirm_date": null,
"transfer_date": null,
"amount_br": "99.85",
"amount_ext": "99.85",
"amount_iof": "1",
"currency_rate": "1",
"currency_ext": "BRL",
"due_date": "{{YYYY-MM-DD}}",
"payment_type_code": "pix-automatico",
"enrollment": {
"status": "ACCEPTED",
"merchant_enrollment_code": "{{unique_enrollment_code}}"
},
"transaction_status": {
"acquirer": "EBANX",
"code": "OK",
"description": "Payment successfully paid",
"description_code": "ACCEPTED"
}
},
"status": "SUCCESS"
} - Confirming the Payment
As soon as the payment is confirmed by the customer's bank, the payment status is modified from
PEtoCOand a Status Update notification is sent.Shell# Sent by EBANX to the merchant notification URL
curl -X POST \
--location 'https://merchant.example.com/callback' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data-urlencode 'operation=payment_status_change' \
--data-urlencode 'notification_type=update' \
--data-urlencode 'hash_codes={{unique_payment_hash}}' \
--data-urlencode 'merchant_payment_code={{unique_merchant_code}}'Using the
hashprovided in the payment response, use the/ws/queryendpoint to get the latest status of the payment.Check the example:
Shellcurl -X POST \
--location 'https://sandbox.ebanxpay.com/ws/query' \
--header 'Content-Type: application/json' \
--data '{
"integration_key": "{{integration_key}}",
"hash": "59acc5f00945fa382ab051651440826da7701533249b3a475"
}'A successful request will return a JSON response like the one below, with a status of
COfor the successful recurring payment.JSON{
"payment": {
"hash": "59acc5f00945fa382ab051651440826da7701533249b3a475",
"country": "BR",
"merchant_payment_code": "{{unique_merchant_code}}",
"status": "CO",
"status_date": "{{YYYY-MM-DD HH:mm:ss}}",
"open_date": "{{YYYY-MM-DD HH:mm:ss}}",
"confirm_date": "{{YYYY-MM-DD HH:mm:ss}}",
"transfer_date": "{{YYYY-MM-DD HH:mm:ss}}",
"amount_br": "99.85",
"amount_ext": "99.85",
"amount_iof": "1",
"currency_rate": "1",
"currency_ext": "BRL",
"due_date": "{{YYYY-MM-DD}}",
"payment_type_code": "pix-automatico",
"transaction_status": {
"acquirer": "EBANX",
"code": "OK",
"description": "Payment successfully paid",
"description_code": "ACCEPTED"
},
"enrollment": {
"status": "ACCEPTED",
"merchant_enrollment_code": "{{unique_enrollment_code}}"
}
},
"status": "SUCCESS"
}Now, for each new billing cycle, simply repeat these steps!
- Congratulations!
You have successfully integrated Pix Automático Recurring Payment.
For more information, refer to theDirect API reference guidechevron_right
Note: Scheduling a new payment vs. retrying an existing one
Pix Automático gives you two distinct ways to act on a payment within a billing cycle, and it's important not to confuse them:
- Scheduling creates a brand-new payment for the cycle, using the
/ws/directendpoint (see Instructions above). - Retrying asks EBANX to attempt liquidation again for a payment that already exists and already failed, using the
/ws/retryendpoint (see Recurring Payment Retries).
You can only ever have one payment per cycle that reaches a processing attempt — that is, one payment that is either confirmed (CO) or that was actually sent to the customer's bank for liquidation and failed (CA), including after all applicable retries. If you try to schedule a second payment for a cycle that already has one of these, the request is rejected with BP-DR-62 — Subscription Cycle error: This cycle already have one payment.
This does not mean every canceled (CA) payment blocks a new schedule attempt. Some cancellation reasons happen before any processing attempt — for example, the bank couldn't respond in time, the amount exceeded the customer's configured limit, or the payment was canceled by the customer or merchant before the due date. In those cases, no liquidation was ever attempted, so the cycle is still open and you can submit a new scheduling request (respecting the usual 2–10 day window).
The table below shows how each cancellation reason (from the Payment Cancellation Reason section) maps to this rule:
| description_code | Was liquidation attempted? | New schedule allowed in the same cycle? |
|---|---|---|
TIMEOUT | No — rejected before reaching the bank's processing window | Yes |
MAX_AMOUNT_EXCEEDED | No — rejected before the processing window | Yes |
CANCELED_BY_PAYER | No — canceled before due_date | Yes |
CANCELED_BY_MERCHANT | No — canceled before due_date | Yes |
INSUFFICIENT_FUNDS_OR_DAILY_LIMIT (no retry policy) | Yes | No |
NOT_ALLOW_RETRY | Yes | No |
EXPIRED_AFTER_3RETRIES | Yes (initial attempt + 3 retries) | No |
EXPIRED_AFTER_7DAYS | Yes (initial attempt, retry window expired) | No |
CO (confirmed) | Yes — successfully | No |
ENROLLMENT_CANCELLED and USER_ACCOUNT_CLOSED are a separate case: they happen when the whole enrollment was cancelled or the bank account was terminated, not just the payment. No further payments — new or retried — can be scheduled under that enrollment at all, in any cycle.
Example: cancellation before liquidation — a new schedule is allowed
{
"payment": {
"hash": "59acc5f00945fa382ab051651440826da7701533249b3a475",
"country": "BR",
"merchant_payment_code": "{{unique_merchant_code}}",
"status": "CA",
"status_date": "{{YYYY-MM-DD HH:mm:ss}}",
"open_date": "{{YYYY-MM-DD HH:mm:ss}}",
"confirm_date": null,
"transfer_date": null,
"amount_br": "99.85",
"amount_ext": "99.85",
"amount_iof": "1",
"currency_rate": "1",
"currency_ext": "BRL",
"due_date": "{{YYYY-MM-DD}}",
"payment_type_code": "pix-automatico",
"transaction_status": {
"acquirer": "EBANX IP",
"code": "NOK",
"description": "External service not available, try again",
"description_code": "TIMEOUT"
},
"enrollment": {
"status": "ACCEPTED",
"merchant_enrollment_code": "{{unique_enrollment_code}}"
}
},
"status": "SUCCESS"
}
Since TIMEOUT happens before any processing attempt, you can submit a new /ws/direct request for the same cycle, as long as the new due_date still falls within the 2–10 day scheduling window.
Example: cancellation after liquidation was attempted — the cycle is closed
{
"payment": {
"hash": "59acc5f00945fa382ab051651440826da7701533249b3a475",
"country": "BR",
"merchant_payment_code": "{{unique_merchant_code}}",
"status": "CA",
"status_date": "{{YYYY-MM-DD HH:mm:ss}}",
"open_date": "{{YYYY-MM-DD HH:mm:ss}}",
"confirm_date": null,
"transfer_date": null,
"amount_br": "99.85",
"amount_ext": "99.85",
"amount_iof": "1",
"currency_rate": "1",
"currency_ext": "BRL",
"due_date": "{{YYYY-MM-DD}}",
"payment_type_code": "pix-automatico",
"transaction_status": {
"acquirer": "EBANX IP",
"code": "NOK",
"description": "Payment cancelled after 3 retries",
"description_code": "EXPIRED_AFTER_3RETRIES"
},
"enrollment": {
"status": "ACCEPTED",
"merchant_enrollment_code": "{{unique_enrollment_code}}"
}
},
"status": "SUCCESS"
}
Here, a processing attempt did happen (and was retried up to the limit), so this cycle is closed. A new /ws/direct request for the same cycle returns BP-DR-62. The next opportunity to charge the customer is the following cycle, since a cancelled payment or a cycle with no charges don't trigger enrollment cancellations.
Still need help?
We hope this article was helpful. If you still have questions, you can explore the following options:
- Merchant support: Contact our support team at integration@ebanx.com for assistance.
- Not a partner yet? Please complete the Merchant Signup Form, and our commercial team will reach out to you.