Recurrences
A recurrence is the payer's mandate: their authorization for you to charge them. It defines who pays, how much, how often and for how long. On this page you will find the endpoints to create, get, list, update and cancel recurrences.
Available Endpoints
- Production:
https://api.pixtopay.com.br/v2/automatic-pix/recurrences
Create recurrence
Creates the recurrence the payer will authorize. The response already carries the authorization QR code.
Route
POST /v2/automatic-pix/recurrences
Headers
{
"Authorization": "YOUR_API_KEY",
"Content-Type": "application/json"
}Body
| Parameter | Type | Required | Description |
|---|---|---|---|
transaction_id | string | Yes | Your identifier for the recurrence. At most 35 characters, unique in your account. It is the identifier the payer's banking app shows, so prefer something meaningful to them. Above 35 characters the request is refused, not truncated. |
object | string | No | Description of the subscription, at most 35 characters (e.g. "Plano Gold mensal"). In journey 3, it is the text shown to the payer on the immediate payment. |
debtor | object | Yes | The payer. It is the same for the whole life of the recurrence. |
debtor.document_number | string | Yes | CPF (11 digits) or CNPJ (14 digits), digits only. The check digit is validated. |
debtor.name | string | Yes | Payer name, at most 100 characters. |
debtor.email | string | No | Valid email, at most 140 characters. |
debtor.address | object | No | Payer address. Optional as a whole, complete if sent: with the object, the four fields below are required. |
debtor.address.street | string | Yes* | Street with number, at most 200 characters. |
debtor.address.city | string | Yes* | City, at most 200 characters. |
debtor.address.state | string | Yes* | State with exactly 2 upper-case letters (e.g. "SP"). |
debtor.address.zip_code | string | Yes* | CEP with exactly 8 digits, no hyphen. |
schedule | object | Yes | The recurrence's calendar. |
schedule.start_date | string | Yes | YYYY-MM-DD. Date from which the recurrence is valid. It must be after today, in Brasília time. |
schedule.end_date | string | No | YYYY-MM-DD, after start_date. Omit it for an open-ended subscription. It cannot be changed afterwards. |
schedule.periodicity | string | Yes | WEEKLY, MONTHLY, QUARTERLY, SEMIANNUAL or ANNUAL. |
amount | number | Yes | Fixed amount of each charge, in reais, with up to 2 decimal places (e.g. 99.90). It is the amount charged every cycle. |
retry_policy | string | Yes | NOT_ALLOWED or ALLOWS_3R_7D. It cannot be changed afterwards. |
business_day_adjust | boolean | No | true to move a due date that falls on a weekend or holiday to the next business day. Default false: the debit happens on the exact date. It can be changed later with PATCH. |
charge_lead_days | integer | No | How many days before each due date PixToPay creates the cycle's charge: 3 to 10. Default 5. Banco Central allows 2, but the minimum here is 3 so a failed day can still be recovered before the D-2 deadline. It can be changed later with PATCH. |
webhook | string | No | URL (max. 255 characters) that receives the events of this recurrence and its charges, and the callback of each payment. See Notifications. Recommended. |
activation_amount | number | No | Amount of the immediate payment of journey 3. When present, the API creates the payment and binds it to the recurrence. |
activation_expires_in | integer | No | For how many seconds the activation payment stays payable. Default 3600 (1 hour), maximum 86400 (24 hours). Only takes effect with activation_amount. |
location_id | integer | No | Only to reuse an existing QR location. When omitted, the API creates one. If in doubt, omit it. |
* Required when debtor.address is sent.
Send only the fields in the table above. Any other field in the body, even a single misspelled name, gets the whole request refused with 400, and nothing is created. The message names the fields that are not accepted:
{ "type": "ValidationError", "message": "`plano`, `valor` is not a field of this endpoint" }Date rules. schedule.start_date must be after today, in Brasília time: today's date is refused. schedule.end_date, when sent, must be after schedule.start_date. Outside these rules the response is 400 naming the field, and nothing is created.
Request example:
curl --location 'https://api.pixtopay.com.br/v2/automatic-pix/recurrences' \
--header 'Authorization: API_KEY' \
--header 'Content-Type: application/json' \
--data-raw '{
"transaction_id": "assinatura-8891",
"object": "Plano Gold mensal",
"debtor": {
"document_number": "12345678909",
"name": "Maria Silva",
"email": "maria.silva@exemplo.com.br",
"address": {
"street": "Rua das Acacias, 128",
"city": "Belo Horizonte",
"state": "MG",
"zip_code": "30140071"
}
},
"schedule": {
"start_date": "2026-10-01",
"end_date": "2027-10-01",
"periodicity": "MONTHLY"
},
"amount": 99.90,
"retry_policy": "ALLOWS_3R_7D",
"business_day_adjust": true,
"charge_lead_days": 5,
"webhook": "https://loja.exemplo.com.br/callbacks/pixtopay"
}'Response model [2xx]
| Parameter | Type | Description |
|---|---|---|
recurrence_id | string | Recurrence identifier. Store it: you use it in every following endpoint. |
status | string | Recurrence status. A new recurrence is born CREATED. |
contract | string | Echo of the transaction_id you sent. It is the identifier the payer sees in their banking app. |
debtor | object | Payer document (document_number) and name (name). Email and address are stored and travel with the charges, but are not echoed. |
schedule | object | start_date, end_date (null if open-ended) and periodicity. |
amount | number | Amount of each charge. |
retry_policy | string | Retry policy. |
business_day_adjust | boolean | Whether a due date on a weekend or holiday moves to the next business day. |
charge_lead_days | integer | How many days in advance each cycle's charge is created. |
journey | string | AWAITING_DEFINITION until the payer authorizes. |
pix_copy_paste | string | The recurrence's Pix copy-and-paste code, as text. It is what the payer pastes in their banking app to authorize. |
qrcode | string | The same code as a base64 PNG image (data URI), ready for <img src="...">. It is the QR code the payer scans. If it is missing, get the recurrence with GET /recurrences/:recurrence_id. |
webhook | string | The recurrence's notification URL, or null. |
activation | object | Only in journey 3 with activation_amount: charge_id and amount of the immediate payment. |
Response model [4xx]
| Parameter | Type | Description |
|---|---|---|
type | string | ValidationError or ProviderError |
message | string | Message describing the error, naming the field |
Response 201:
{
"recurrence_id": "RR9012345620260922f3a1c7b28e4",
"status": "CREATED",
"contract": "assinatura-8891",
"debtor": {
"document_number": "12345678909",
"name": "Maria Silva"
},
"schedule": {
"start_date": "2026-10-01",
"end_date": "2027-10-01",
"periodicity": "MONTHLY"
},
"amount": 99.9,
"retry_policy": "ALLOWS_3R_7D",
"business_day_adjust": false,
"charge_lead_days": 5,
"journey": "AWAITING_DEFINITION",
"pix_copy_paste": "00020126850014br.gov.bcb.pix2563qrcode.exemplo/v2/9f2a...6304A1B2",
"qrcode": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUg...",
"webhook": "https://loja.exemplo.com.br/callbacks/pixtopay"
}Journey 3: authorize and charge in the same scan
Send activation_amount so that the same QR code charges an immediate payment right away and authorizes the recurrence.
Request example:
curl --location 'https://api.pixtopay.com.br/v2/automatic-pix/recurrences' \
--header 'Authorization: API_KEY' \
--header 'Content-Type: application/json' \
--data-raw '{
"transaction_id": "assinatura-8892",
"object": "Plano Gold mensal",
"debtor": {
"document_number": "12345678909",
"name": "Maria Silva"
},
"schedule": {
"start_date": "2026-11-01",
"periodicity": "MONTHLY"
},
"amount": 99.90,
"retry_policy": "ALLOWS_3R_7D",
"activation_amount": 99.90,
"activation_expires_in": 3600,
"webhook": "https://loja.exemplo.com.br/callbacks/pixtopay"
}'Response 201:
{
"recurrence_id": "RR9012345620260922b7d2e9a14c1",
"status": "CREATED",
"contract": "assinatura-8892",
"debtor": {
"document_number": "12345678909",
"name": "Maria Silva"
},
"schedule": {
"start_date": "2026-11-01",
"end_date": null,
"periodicity": "MONTHLY"
},
"amount": 99.9,
"retry_policy": "ALLOWS_3R_7D",
"business_day_adjust": false,
"charge_lead_days": 5,
"journey": "AWAITING_DEFINITION",
"pix_copy_paste": "00020126850014br.gov.bcb.pix2563qrcode.exemplo/v2/7c41...63041E9F",
"qrcode": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUg...",
"activation": {
"charge_id": "c2a8e41f70b94d3ca5e61b8027fd394a",
"amount": 99.9
},
"webhook": "https://loja.exemplo.com.br/callbacks/pixtopay"
}The activation payment is separate from the cycles: automatic charges start at schedule.start_date, as on any recurrence. To charge the activation today and the next debit a month from now, send start_date one month ahead. It appears in GET /charges as a charge of the recurrence, with "type": "activation", and reaches you as a paid Pix deposit, with transaction_id equal to <recurrence transaction_id>-ativacao.
Response 400 duplicate transaction_id:
{
"type": "ValidationError",
"message": "body.transaction_id already exists"
}Response 400 unknown field:
{
"type": "ValidationError",
"message": "`plano`, `valor` is not a field of this endpoint"
}See every message of this endpoint in Errors.
Get recurrence
Gets a recurrence with its current state, fetched at the time of the call. This is the call to find out whether the payer has authorized.
Route
GET /v2/automatic-pix/recurrences/:recurrence_id
Headers
{
"Authorization": "YOUR_API_KEY"
}Parameters
| Parameter | Where | Required | Description |
|---|---|---|---|
recurrence_id | path | Yes | The recurrence_id returned on creation. |
For a journey 3 recurrence (created with activation_amount), the read returns the combined QR, which charges and authorizes in the same scan. Once the activation payment has expired unpaid, the read answers with pix_copy_paste: null and no qrcode: the recurrence can no longer be authorized with its activation. Cancel it and create a new one.
A recurrence that has ended (CANCELLED, REJECTED or EXPIRED) is read with pix_copy_paste: null and no qrcode: it has no QR to show.
Request example:
curl --location 'https://api.pixtopay.com.br/v2/automatic-pix/recurrences/RR9012345620260922f3a1c7b28e4' \
--header 'Authorization: API_KEY'Response 200:
{
"recurrence_id": "RR9012345620260922f3a1c7b28e4",
"status": "APPROVED",
"contract": "assinatura-8891",
"debtor": {
"document_number": "12345678909",
"name": "Maria Silva"
},
"schedule": {
"start_date": "2026-10-01",
"end_date": "2027-10-01",
"periodicity": "MONTHLY"
},
"amount": 99.9,
"retry_policy": "ALLOWS_3R_7D",
"business_day_adjust": false,
"charge_lead_days": 5,
"journey": "JOURNEY_2",
"pix_copy_paste": "00020126850014br.gov.bcb.pix2563qrcode.exemplo/v2/9f2a...6304A1B2",
"qrcode": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUg...",
"webhook": "https://loja.exemplo.com.br/callbacks/pixtopay"
}Same format as the creation response, with status and journey updated.
Response 404:
{
"message": "Recurrence not found"
}The 404 covers both an identifier that does not exist and one that does not belong to your account. Both answer the same way, on purpose.
List recurrences
Lists the recurrences you created in a period, newest first.
Route
GET /v2/automatic-pix/recurrences
Headers
{
"Authorization": "YOUR_API_KEY"
}Query Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
start | string (ISO 8601) | Yes | Start of the period, with time zone (e.g. 2026-09-01T00:00:00-03:00). Compared with the creation date. |
end | string (ISO 8601) | Yes | End of the period, with time zone. |
page | integer | No | Page, starting at 0. Default 0. |
page_size | integer | No | Items per page. Default and maximum 100: larger values become 100. |
Request example:
curl --location 'https://api.pixtopay.com.br/v2/automatic-pix/recurrences?start=2026-09-01T00:00:00Z&end=2026-10-01T00:00:00Z&page=0&page_size=100' \
--header 'Authorization: API_KEY'Response 200:
{
"pagination": {
"current_page": 0,
"page_size": 100,
"total_pages": 3,
"total_items": 260
},
"recurrences": [
{
"recurrence_id": "RR9012345620260922f3a1c7b28e4",
"status": "APPROVED",
"contract": "assinatura-8891",
"debtor": { "document_number": "12345678909", "name": "Maria Silva" },
"schedule": {
"start_date": "2026-10-01",
"end_date": "2027-10-01",
"periodicity": "MONTHLY"
},
"amount": 99.9,
"retry_policy": "ALLOWS_3R_7D",
"business_day_adjust": false,
"charge_lead_days": 5,
"journey": "JOURNEY_2",
"pix_copy_paste": "00020126850014br.gov.bcb.pix2563qrcode.exemplo/v2/9f2a...6304A1B2",
"webhook": "https://loja.exemplo.com.br/callbacks/pixtopay"
}
]
}- The list does not include
qrcode, onlypix_copy_paste. For the image, get the recurrence individually.
Response 400 missing period:
{
"type": "ValidationError",
"message": "start and end are required"
}Update or cancel recurrence
Route
PATCH /v2/automatic-pix/recurrences/:recurrence_id
Headers
{
"Authorization": "YOUR_API_KEY",
"Content-Type": "application/json"
}Body
Send at least one of these fields:
| Parameter | Type | Description |
|---|---|---|
debtor_name | string | Corrects the payer's name. At most 140 characters; prefer up to 100, the limit of the name on charges. |
start_date | string | YYYY-MM-DD. Moves the start date later or earlier. Same rule as creation: after today, in Brasília time. |
status | string | CANCELLED. Ends the recurrence. |
webhook | string | Replaces the recurrence's notification URL. "" or null clears it. |
business_day_adjust | boolean | Turns the move to the next business day on or off. Applies to charges not yet created. |
charge_lead_days | integer | New lead time, 3 to 10 days. Applies to charges not yet created. |
Amount, periodicity, end date and retry policy do not change. Sending amount, periodicity, end_date, retry_policy, object, debtor, schedule, location_id or contract is refused with 400, naming the field. A price or plan change is a new recurrence: cancel the current one, create another with a new transaction_id and ask the payer to authorize again.
Cancelling is the only way to end a recurrence, and CANCELLED is the only status you can set. There is no deletion. Cancelling the recurrence does not cancel charges already issued: if a cycle's charge is waiting for its due date and you do not want to collect it, cancel it too, with PATCH /charges/:charge_id.
Replacing the webhook:
- A
PATCHwith onlywebhookjust stores the new URL and answers. - The change also applies to the recurrence's pending charges: their payment is notified at the new URL. Charges already paid are not touched.
- The journey 3 activation payment keeps the URL in effect when the recurrence was created.
Request example (cancel):
curl --location --request PATCH 'https://api.pixtopay.com.br/v2/automatic-pix/recurrences/RR9012345620260922f3a1c7b28e4' \
--header 'Authorization: API_KEY' \
--header 'Content-Type: application/json' \
--data-raw '{
"status": "CANCELLED"
}'Request example (correct the name):
curl --location --request PATCH 'https://api.pixtopay.com.br/v2/automatic-pix/recurrences/RR9012345620260922f3a1c7b28e4' \
--header 'Authorization: API_KEY' \
--header 'Content-Type: application/json' \
--data-raw '{
"debtor_name": "Maria S. Silva"
}'Response 200:
{
"recurrence_id": "RR9012345620260922f3a1c7b28e4",
"status": "APPROVED",
"contract": "assinatura-8891",
"debtor": {
"document_number": "12345678909",
"name": "Maria S. Silva"
},
"schedule": {
"start_date": "2026-10-01",
"end_date": "2027-10-01",
"periodicity": "MONTHLY"
},
"amount": 99.9,
"retry_policy": "ALLOWS_3R_7D",
"business_day_adjust": false,
"charge_lead_days": 5,
"journey": "JOURNEY_2",
"pix_copy_paste": "00020126850014br.gov.bcb.pix2563qrcode.exemplo/v2/9f2a...6304A1B2",
"qrcode": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUg...",
"webhook": "https://loja.exemplo.com.br/callbacks/pixtopay"
}A PATCH whose result is CANCELLED, REJECTED or EXPIRED answers with pix_copy_paste: null and no qrcode: a recurrence that has ended has no QR to show.
Response 400 field that cannot be changed:
{
"type": "ValidationError",
"message": "`amount`, `periodicity` cannot be changed after a recurrence is created. A recurrence whose value, cadence or end date must change has to be cancelled and recreated under a new contract, and re-authorised by the payer"
}Response 400 empty body:
{
"type": "ValidationError",
"message": "body must set at least one changeable field: `debtor_name`, `start_date`, `status`, `webhook`, `business_day_adjust`, `charge_lead_days`"
}