Update Payment Plan
curl --request PUT \
--url https://getbill.io/external-api/v1/debts/{id}/payment-plan \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"plan_start_date": "<string>",
"first_payment_amount": 123,
"installments": [
{}
]
}
'import requests
url = "https://getbill.io/external-api/v1/debts/{id}/payment-plan"
payload = {
"plan_start_date": "<string>",
"first_payment_amount": 123,
"installments": [{}]
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.put(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'PUT',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({plan_start_date: '<string>', first_payment_amount: 123, installments: [{}]})
};
fetch('https://getbill.io/external-api/v1/debts/{id}/payment-plan', 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://getbill.io/external-api/v1/debts/{id}/payment-plan",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "PUT",
CURLOPT_POSTFIELDS => json_encode([
'plan_start_date' => '<string>',
'first_payment_amount' => 123,
'installments' => [
[
]
]
]),
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://getbill.io/external-api/v1/debts/{id}/payment-plan"
payload := strings.NewReader("{\n \"plan_start_date\": \"<string>\",\n \"first_payment_amount\": 123,\n \"installments\": [\n {}\n ]\n}")
req, _ := http.NewRequest("PUT", 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.put("https://getbill.io/external-api/v1/debts/{id}/payment-plan")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"plan_start_date\": \"<string>\",\n \"first_payment_amount\": 123,\n \"installments\": [\n {}\n ]\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://getbill.io/external-api/v1/debts/{id}/payment-plan")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Put.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"plan_start_date\": \"<string>\",\n \"first_payment_amount\": 123,\n \"installments\": [\n {}\n ]\n}"
response = http.request(request)
puts response.read_bodyDebts API
Update Payment Plan
Replace the pending schedule of a debt payment plan
PUT
/
external-api
/
v1
/
debts
/
{id}
/
payment-plan
Update Payment Plan
curl --request PUT \
--url https://getbill.io/external-api/v1/debts/{id}/payment-plan \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"plan_start_date": "<string>",
"first_payment_amount": 123,
"installments": [
{}
]
}
'import requests
url = "https://getbill.io/external-api/v1/debts/{id}/payment-plan"
payload = {
"plan_start_date": "<string>",
"first_payment_amount": 123,
"installments": [{}]
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.put(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'PUT',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({plan_start_date: '<string>', first_payment_amount: 123, installments: [{}]})
};
fetch('https://getbill.io/external-api/v1/debts/{id}/payment-plan', 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://getbill.io/external-api/v1/debts/{id}/payment-plan",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "PUT",
CURLOPT_POSTFIELDS => json_encode([
'plan_start_date' => '<string>',
'first_payment_amount' => 123,
'installments' => [
[
]
]
]),
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://getbill.io/external-api/v1/debts/{id}/payment-plan"
payload := strings.NewReader("{\n \"plan_start_date\": \"<string>\",\n \"first_payment_amount\": 123,\n \"installments\": [\n {}\n ]\n}")
req, _ := http.NewRequest("PUT", 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.put("https://getbill.io/external-api/v1/debts/{id}/payment-plan")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"plan_start_date\": \"<string>\",\n \"first_payment_amount\": 123,\n \"installments\": [\n {}\n ]\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://getbill.io/external-api/v1/debts/{id}/payment-plan")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Put.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"plan_start_date\": \"<string>\",\n \"first_payment_amount\": 123,\n \"installments\": [\n {}\n ]\n}"
response = http.request(request)
puts response.read_bodyOverview
Replaces the non-paid installments of a payment plan. Existing paid installments are preserved, so recorded payments are not lost when a partner sends a new negotiated schedule. New installment IDs are returned as encrypted stable IDs. Store them if you later need to mark a specific installment as paid. For grouped debts, call this endpoint with any debt ID in the group. GetBill creates one shared schedule whose total must match the combined remaining balance of all non-archived debts in the group. The response exposesgrouped, plan_debt_id, and group_debt_ids; use the returned installment IDs without trying to assign individual schedule lines to individual debts.
This endpoint targets a known debt by its GetBill encrypted ID. If your system sends the complete view of a campaign, send the payment plan in
rows[].payment_plan of the campaign snapshot instead.Authentication
Requires a valid OAuth 2.0 access token with thedebts:write scope.
Request
string
required
Encrypted debt ID.
string
Optional plan start date, in
YYYY-MM-DD or ISO 8601 format. Omit or send null to clear the previous value when replacing the plan.number
Optional positive first payment amount. When provided, it must match the first installment amount and cannot exceed the debt or debt group’s remaining amount. Omit or send
null to clear the previous value when replacing the plan.array
required
New schedule lines. Each line requires
amount and payment_date. The installment amounts must total the current remaining amount of the debt, or the combined remaining amount for a grouped debt.Example
curl -X PUT "/external-api/v1/debts/debt_id/payment-plan" \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"plan_start_date": "2026-08-01",
"first_payment_amount": 100,
"installments": [
{"amount": 100, "payment_date": "2026-08-01"},
{"amount": 200, "payment_date": "2026-09-01"}
]
}'