Criar Cobrança Agendada
curl --request POST \
--url https://garu.com.br/api/v1/scheduled-charges \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"customerId": 123,
"amount": 123,
"type": "<string>",
"dueDate": "<string>",
"methods": [
{}
],
"productId": 123,
"recurrence": {
"interval": "<string>",
"intervalCount": 123,
"endsAfter": 123,
"endsOn": "<string>"
},
"trialDays": 123,
"description": "<string>",
"maxRecoveryDays": 123,
"externalReference": "<string>",
"metadata": {}
}
'import requests
url = "https://garu.com.br/api/v1/scheduled-charges"
payload = {
"customerId": 123,
"amount": 123,
"type": "<string>",
"dueDate": "<string>",
"methods": [{}],
"productId": 123,
"recurrence": {
"interval": "<string>",
"intervalCount": 123,
"endsAfter": 123,
"endsOn": "<string>"
},
"trialDays": 123,
"description": "<string>",
"maxRecoveryDays": 123,
"externalReference": "<string>",
"metadata": {}
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
customerId: 123,
amount: 123,
type: '<string>',
dueDate: '<string>',
methods: [{}],
productId: 123,
recurrence: {interval: '<string>', intervalCount: 123, endsAfter: 123, endsOn: '<string>'},
trialDays: 123,
description: '<string>',
maxRecoveryDays: 123,
externalReference: '<string>',
metadata: {}
})
};
fetch('https://garu.com.br/api/v1/scheduled-charges', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://garu.com.br/api/v1/scheduled-charges",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'customerId' => 123,
'amount' => 123,
'type' => '<string>',
'dueDate' => '<string>',
'methods' => [
[
]
],
'productId' => 123,
'recurrence' => [
'interval' => '<string>',
'intervalCount' => 123,
'endsAfter' => 123,
'endsOn' => '<string>'
],
'trialDays' => 123,
'description' => '<string>',
'maxRecoveryDays' => 123,
'externalReference' => '<string>',
'metadata' => [
]
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://garu.com.br/api/v1/scheduled-charges"
payload := strings.NewReader("{\n \"customerId\": 123,\n \"amount\": 123,\n \"type\": \"<string>\",\n \"dueDate\": \"<string>\",\n \"methods\": [\n {}\n ],\n \"productId\": 123,\n \"recurrence\": {\n \"interval\": \"<string>\",\n \"intervalCount\": 123,\n \"endsAfter\": 123,\n \"endsOn\": \"<string>\"\n },\n \"trialDays\": 123,\n \"description\": \"<string>\",\n \"maxRecoveryDays\": 123,\n \"externalReference\": \"<string>\",\n \"metadata\": {}\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://garu.com.br/api/v1/scheduled-charges")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"customerId\": 123,\n \"amount\": 123,\n \"type\": \"<string>\",\n \"dueDate\": \"<string>\",\n \"methods\": [\n {}\n ],\n \"productId\": 123,\n \"recurrence\": {\n \"interval\": \"<string>\",\n \"intervalCount\": 123,\n \"endsAfter\": 123,\n \"endsOn\": \"<string>\"\n },\n \"trialDays\": 123,\n \"description\": \"<string>\",\n \"maxRecoveryDays\": 123,\n \"externalReference\": \"<string>\",\n \"metadata\": {}\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://garu.com.br/api/v1/scheduled-charges")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"customerId\": 123,\n \"amount\": 123,\n \"type\": \"<string>\",\n \"dueDate\": \"<string>\",\n \"methods\": [\n {}\n ],\n \"productId\": 123,\n \"recurrence\": {\n \"interval\": \"<string>\",\n \"intervalCount\": 123,\n \"endsAfter\": 123,\n \"endsOn\": \"<string>\"\n },\n \"trialDays\": 123,\n \"description\": \"<string>\",\n \"maxRecoveryDays\": 123,\n \"externalReference\": \"<string>\",\n \"metadata\": {}\n}"
response = http.request(request)
puts response.read_bodyCobranças Agendadas
Criar Cobrança Agendada
Agende uma cobrança PIX ou Boleto para um cliente cadastrado
POST
/
api
/
v1
/
scheduled-charges
Criar Cobrança Agendada
curl --request POST \
--url https://garu.com.br/api/v1/scheduled-charges \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"customerId": 123,
"amount": 123,
"type": "<string>",
"dueDate": "<string>",
"methods": [
{}
],
"productId": 123,
"recurrence": {
"interval": "<string>",
"intervalCount": 123,
"endsAfter": 123,
"endsOn": "<string>"
},
"trialDays": 123,
"description": "<string>",
"maxRecoveryDays": 123,
"externalReference": "<string>",
"metadata": {}
}
'import requests
url = "https://garu.com.br/api/v1/scheduled-charges"
payload = {
"customerId": 123,
"amount": 123,
"type": "<string>",
"dueDate": "<string>",
"methods": [{}],
"productId": 123,
"recurrence": {
"interval": "<string>",
"intervalCount": 123,
"endsAfter": 123,
"endsOn": "<string>"
},
"trialDays": 123,
"description": "<string>",
"maxRecoveryDays": 123,
"externalReference": "<string>",
"metadata": {}
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
customerId: 123,
amount: 123,
type: '<string>',
dueDate: '<string>',
methods: [{}],
productId: 123,
recurrence: {interval: '<string>', intervalCount: 123, endsAfter: 123, endsOn: '<string>'},
trialDays: 123,
description: '<string>',
maxRecoveryDays: 123,
externalReference: '<string>',
metadata: {}
})
};
fetch('https://garu.com.br/api/v1/scheduled-charges', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://garu.com.br/api/v1/scheduled-charges",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'customerId' => 123,
'amount' => 123,
'type' => '<string>',
'dueDate' => '<string>',
'methods' => [
[
]
],
'productId' => 123,
'recurrence' => [
'interval' => '<string>',
'intervalCount' => 123,
'endsAfter' => 123,
'endsOn' => '<string>'
],
'trialDays' => 123,
'description' => '<string>',
'maxRecoveryDays' => 123,
'externalReference' => '<string>',
'metadata' => [
]
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://garu.com.br/api/v1/scheduled-charges"
payload := strings.NewReader("{\n \"customerId\": 123,\n \"amount\": 123,\n \"type\": \"<string>\",\n \"dueDate\": \"<string>\",\n \"methods\": [\n {}\n ],\n \"productId\": 123,\n \"recurrence\": {\n \"interval\": \"<string>\",\n \"intervalCount\": 123,\n \"endsAfter\": 123,\n \"endsOn\": \"<string>\"\n },\n \"trialDays\": 123,\n \"description\": \"<string>\",\n \"maxRecoveryDays\": 123,\n \"externalReference\": \"<string>\",\n \"metadata\": {}\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://garu.com.br/api/v1/scheduled-charges")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"customerId\": 123,\n \"amount\": 123,\n \"type\": \"<string>\",\n \"dueDate\": \"<string>\",\n \"methods\": [\n {}\n ],\n \"productId\": 123,\n \"recurrence\": {\n \"interval\": \"<string>\",\n \"intervalCount\": 123,\n \"endsAfter\": 123,\n \"endsOn\": \"<string>\"\n },\n \"trialDays\": 123,\n \"description\": \"<string>\",\n \"maxRecoveryDays\": 123,\n \"externalReference\": \"<string>\",\n \"metadata\": {}\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://garu.com.br/api/v1/scheduled-charges")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"customerId\": 123,\n \"amount\": 123,\n \"type\": \"<string>\",\n \"dueDate\": \"<string>\",\n \"methods\": [\n {}\n ],\n \"productId\": 123,\n \"recurrence\": {\n \"interval\": \"<string>\",\n \"intervalCount\": 123,\n \"endsAfter\": 123,\n \"endsOn\": \"<string>\"\n },\n \"trialDays\": 123,\n \"description\": \"<string>\",\n \"maxRecoveryDays\": 123,\n \"externalReference\": \"<string>\",\n \"metadata\": {}\n}"
response = http.request(request)
puts response.read_bodyVisão Geral
Cria uma cobrança agendada — avulsa (one_time) ou recorrente (recurring) — para uma data futura. A Garu envia o e-mail ao cliente no dia do vencimento e dispara webhooks no ciclo de vida. Para recorrência debitada automaticamente, combine type: "recurring" com methods: ["pix_automatic"] (veja Pix Automático).
Cadastre o cliente primeiro via dashboard ou API — veja
Cadastro de clientes. O
customerId é o ID numérico
interno do cliente (não o uuid público de /api/v1/customers) — as duas
APIs ainda não compartilham um identificador cruzado.Exemplo de Requisição
curl -X POST https://garu.com.br/api/v1/scheduled-charges \
-H "Authorization: Bearer sk_test_sua_chave" \
-H "Content-Type: application/json" \
-H "X-Idempotency-Key: 6c4c2a1e-4c2b-4f1c-9a8d-1b2e3f4a5b6c" \
-d '{
"customerId": 42,
"amount": 297.50,
"type": "one_time",
"dueDate": "2026-06-15",
"methods": ["pix", "boleto"],
"description": "Mensalidade Junho"
}'
import { Garu } from '@garuhq/node';
const garu = new Garu({ apiKey: process.env.GARU_API_KEY });
const charge = await garu.scheduledCharges.create({
customerId: 42,
amount: 297.5,
type: 'one_time',
dueDate: '2026-06-15',
methods: ['pix', 'boleto'],
description: 'Mensalidade Junho'
});
console.log(charge.id); // sch_abc123
import requests
import os
import uuid
response = requests.post(
"https://garu.com.br/api/v1/scheduled-charges",
headers={
"Authorization": f"Bearer {os.environ['GARU_API_KEY']}",
"X-Idempotency-Key": str(uuid.uuid4())
},
json={
"customerId": 42,
"amount": 297.50,
"type": "one_time",
"dueDate": "2026-06-15",
"methods": ["pix", "boleto"],
"description": "Mensalidade Junho"
}
)
print(response.json()["id"]) # sch_abc123
Recorrente com Pix Automático
curl -X POST https://garu.com.br/api/v1/scheduled-charges \
-H "Authorization: Bearer sk_live_xxx" \
-H "Content-Type: application/json" \
-d '{
"customerId": 42,
"productId": 456,
"amount": 297.50,
"type": "recurring",
"dueDate": "2026-06-15",
"methods": ["pix_automatic"],
"recurrence": { "interval": "monthly", "intervalCount": 1, "endsAfter": 12 },
"description": "Plano Premium - mensal"
}'
Parâmetros
number
required
ID do cliente no Garu (já cadastrado neste seller).
number
required
Valor em BRL decimal (ex:
297.50). Não use centavos.string
required
Tipo da cobrança:
one_time (avulsa) ou recurring (recorrente). pix_automatic exige recurring.string
required
Data de vencimento em
YYYY-MM-DD, fuso de São Paulo. Deve ser hoje ou futura.array
required
Métodos oferecidos ao cliente. Aceita
["pix"], ["boleto"], ["pix", "boleto"] ou ["pix_automatic"]. Usar pix_automatic exige type: "recurring" e um productId cujo produto tenha pixAutomatic: true.number
ID de um produto opcional. Quando informado, aparece vinculado à cobrança no dashboard. Obrigatório quando
methods inclui pix_automatic.object
Configuração da recorrência (use com
type: "recurring").Show campos de recurrence
Show campos de recurrence
string
required
Frequência:
weekly, biweekly, monthly, bimonthly, quarterly, biannual ou yearly.number
Multiplicador do intervalo (ex:
interval: "monthly" + intervalCount: 2 = a cada 2 meses).number
Encerra após este número de ciclos. Opcional.
string
Data final da recorrência em
YYYY-MM-DD. Opcional.number
Dias de teste gratuito antes do primeiro ciclo (
1–365). Apenas para type: "recurring".string
Texto livre exibido no e-mail do cliente e na página de pagamento. Até 500 caracteres.
number
default:"14"
Janela, em dias (inteiro de
1 a 365), para a recuperação automática de uma
cobrança que o cron diário tenha perdido — se o disparo do dueDate falhar, a
Garu segue tentando dentro dessa janela. Omitir usa o padrão do sistema (14).
Também aparece no objeto retornado.string
Identificador interno seu (até 255 caracteres). Útil para reconciliação.
object
JSON livre. Persistido como JSONB; não interpretado pela Garu.
Idempotência
O SDK Node anexa o headerX-Idempotency-Key: <uuid> automaticamente em toda chamada. A mesma chave devolve a série originalmente criada por 24h, em vez de agendar uma cobrança duplicada — seguro para retry após timeout de rede.
Resposta
{
"id": "sch_abc123",
"sellerId": 10,
"customerId": 42,
"productId": null,
"amount": 297.5,
"description": "Mensalidade Junho",
"type": "one_time",
"dueDate": "2026-06-15",
"methods": ["pix", "boleto"],
"recurrence": null,
"status": "scheduled",
"subscriptionId": null,
"trialEndsAt": null,
"cancelAtPeriodEnd": false,
"maxRecoveryDays": 14,
"externalReference": null,
"metadata": null,
"createdAt": "2026-05-01T12:00:00Z",
"updatedAt": "2026-05-01T12:00:00Z"
}
Was this page helpful?