Create Followup
curl --request POST \
--url https://getbill.io/external-api/v1/followups \
--header 'Authorization: <authorization>' \
--header 'Content-Type: <content-type>' \
--data '
{
"debt_id": "<string>",
"type": "<string>",
"status": "<string>",
"call_date": "<string>",
"scheduled_at": "<string>",
"summary": "<string>",
"notes": "<string>",
"call_id": "<string>",
"audio_url": "<string>",
"duration_ms": 123,
"phone_number_used": "<string>",
"direction": "<string>",
"disconnection_reason": "<string>",
"is_retry": true
}
'import requests
url = "https://getbill.io/external-api/v1/followups"
payload = {
"debt_id": "<string>",
"type": "<string>",
"status": "<string>",
"call_date": "<string>",
"scheduled_at": "<string>",
"summary": "<string>",
"notes": "<string>",
"call_id": "<string>",
"audio_url": "<string>",
"duration_ms": 123,
"phone_number_used": "<string>",
"direction": "<string>",
"disconnection_reason": "<string>",
"is_retry": True
}
headers = {
"Authorization": "<authorization>",
"Content-Type": "<content-type>"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: '<authorization>', 'Content-Type': '<content-type>'},
body: JSON.stringify({
debt_id: '<string>',
type: '<string>',
status: '<string>',
call_date: '<string>',
scheduled_at: '<string>',
summary: '<string>',
notes: '<string>',
call_id: '<string>',
audio_url: '<string>',
duration_ms: 123,
phone_number_used: '<string>',
direction: '<string>',
disconnection_reason: '<string>',
is_retry: true
})
};
fetch('https://getbill.io/external-api/v1/followups', 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/followups",
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([
'debt_id' => '<string>',
'type' => '<string>',
'status' => '<string>',
'call_date' => '<string>',
'scheduled_at' => '<string>',
'summary' => '<string>',
'notes' => '<string>',
'call_id' => '<string>',
'audio_url' => '<string>',
'duration_ms' => 123,
'phone_number_used' => '<string>',
'direction' => '<string>',
'disconnection_reason' => '<string>',
'is_retry' => true
]),
CURLOPT_HTTPHEADER => [
"Authorization: <authorization>",
"Content-Type: <content-type>"
],
]);
$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/followups"
payload := strings.NewReader("{\n \"debt_id\": \"<string>\",\n \"type\": \"<string>\",\n \"status\": \"<string>\",\n \"call_date\": \"<string>\",\n \"scheduled_at\": \"<string>\",\n \"summary\": \"<string>\",\n \"notes\": \"<string>\",\n \"call_id\": \"<string>\",\n \"audio_url\": \"<string>\",\n \"duration_ms\": 123,\n \"phone_number_used\": \"<string>\",\n \"direction\": \"<string>\",\n \"disconnection_reason\": \"<string>\",\n \"is_retry\": true\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "<authorization>")
req.Header.Add("Content-Type", "<content-type>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://getbill.io/external-api/v1/followups")
.header("Authorization", "<authorization>")
.header("Content-Type", "<content-type>")
.body("{\n \"debt_id\": \"<string>\",\n \"type\": \"<string>\",\n \"status\": \"<string>\",\n \"call_date\": \"<string>\",\n \"scheduled_at\": \"<string>\",\n \"summary\": \"<string>\",\n \"notes\": \"<string>\",\n \"call_id\": \"<string>\",\n \"audio_url\": \"<string>\",\n \"duration_ms\": 123,\n \"phone_number_used\": \"<string>\",\n \"direction\": \"<string>\",\n \"disconnection_reason\": \"<string>\",\n \"is_retry\": true\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://getbill.io/external-api/v1/followups")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = '<authorization>'
request["Content-Type"] = '<content-type>'
request.body = "{\n \"debt_id\": \"<string>\",\n \"type\": \"<string>\",\n \"status\": \"<string>\",\n \"call_date\": \"<string>\",\n \"scheduled_at\": \"<string>\",\n \"summary\": \"<string>\",\n \"notes\": \"<string>\",\n \"call_id\": \"<string>\",\n \"audio_url\": \"<string>\",\n \"duration_ms\": 123,\n \"phone_number_used\": \"<string>\",\n \"direction\": \"<string>\",\n \"disconnection_reason\": \"<string>\",\n \"is_retry\": true\n}"
response = http.request(request)
puts response.read_body{
"error": false,
"message": "Followup created successfully",
"data": {
"id": "abc123def456",
"debt_id": "xyz789ghi012",
"status": "scheduled",
"type": "call",
"call_date": null,
"scheduled_at": "2024-01-25T10:00:00+00:00",
"summary": "Follow-up call to discuss payment plan",
"notes": "Customer previously expressed interest in monthly payment schedule",
"call_id": null,
"audio_url": null,
"pdf_url": null,
"duration_ms": null,
"disconnection_reason": null,
"direction": null,
"phone_number_used": null,
"is_retry": false,
"processed_at": "2024-01-22T15:30:00+00:00"
}
}
Followups API
Create Followup
Create a new followup activity for a debt
POST
/
external-api
/
v1
/
followups
Create Followup
curl --request POST \
--url https://getbill.io/external-api/v1/followups \
--header 'Authorization: <authorization>' \
--header 'Content-Type: <content-type>' \
--data '
{
"debt_id": "<string>",
"type": "<string>",
"status": "<string>",
"call_date": "<string>",
"scheduled_at": "<string>",
"summary": "<string>",
"notes": "<string>",
"call_id": "<string>",
"audio_url": "<string>",
"duration_ms": 123,
"phone_number_used": "<string>",
"direction": "<string>",
"disconnection_reason": "<string>",
"is_retry": true
}
'import requests
url = "https://getbill.io/external-api/v1/followups"
payload = {
"debt_id": "<string>",
"type": "<string>",
"status": "<string>",
"call_date": "<string>",
"scheduled_at": "<string>",
"summary": "<string>",
"notes": "<string>",
"call_id": "<string>",
"audio_url": "<string>",
"duration_ms": 123,
"phone_number_used": "<string>",
"direction": "<string>",
"disconnection_reason": "<string>",
"is_retry": True
}
headers = {
"Authorization": "<authorization>",
"Content-Type": "<content-type>"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: '<authorization>', 'Content-Type': '<content-type>'},
body: JSON.stringify({
debt_id: '<string>',
type: '<string>',
status: '<string>',
call_date: '<string>',
scheduled_at: '<string>',
summary: '<string>',
notes: '<string>',
call_id: '<string>',
audio_url: '<string>',
duration_ms: 123,
phone_number_used: '<string>',
direction: '<string>',
disconnection_reason: '<string>',
is_retry: true
})
};
fetch('https://getbill.io/external-api/v1/followups', 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/followups",
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([
'debt_id' => '<string>',
'type' => '<string>',
'status' => '<string>',
'call_date' => '<string>',
'scheduled_at' => '<string>',
'summary' => '<string>',
'notes' => '<string>',
'call_id' => '<string>',
'audio_url' => '<string>',
'duration_ms' => 123,
'phone_number_used' => '<string>',
'direction' => '<string>',
'disconnection_reason' => '<string>',
'is_retry' => true
]),
CURLOPT_HTTPHEADER => [
"Authorization: <authorization>",
"Content-Type: <content-type>"
],
]);
$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/followups"
payload := strings.NewReader("{\n \"debt_id\": \"<string>\",\n \"type\": \"<string>\",\n \"status\": \"<string>\",\n \"call_date\": \"<string>\",\n \"scheduled_at\": \"<string>\",\n \"summary\": \"<string>\",\n \"notes\": \"<string>\",\n \"call_id\": \"<string>\",\n \"audio_url\": \"<string>\",\n \"duration_ms\": 123,\n \"phone_number_used\": \"<string>\",\n \"direction\": \"<string>\",\n \"disconnection_reason\": \"<string>\",\n \"is_retry\": true\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "<authorization>")
req.Header.Add("Content-Type", "<content-type>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://getbill.io/external-api/v1/followups")
.header("Authorization", "<authorization>")
.header("Content-Type", "<content-type>")
.body("{\n \"debt_id\": \"<string>\",\n \"type\": \"<string>\",\n \"status\": \"<string>\",\n \"call_date\": \"<string>\",\n \"scheduled_at\": \"<string>\",\n \"summary\": \"<string>\",\n \"notes\": \"<string>\",\n \"call_id\": \"<string>\",\n \"audio_url\": \"<string>\",\n \"duration_ms\": 123,\n \"phone_number_used\": \"<string>\",\n \"direction\": \"<string>\",\n \"disconnection_reason\": \"<string>\",\n \"is_retry\": true\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://getbill.io/external-api/v1/followups")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = '<authorization>'
request["Content-Type"] = '<content-type>'
request.body = "{\n \"debt_id\": \"<string>\",\n \"type\": \"<string>\",\n \"status\": \"<string>\",\n \"call_date\": \"<string>\",\n \"scheduled_at\": \"<string>\",\n \"summary\": \"<string>\",\n \"notes\": \"<string>\",\n \"call_id\": \"<string>\",\n \"audio_url\": \"<string>\",\n \"duration_ms\": 123,\n \"phone_number_used\": \"<string>\",\n \"direction\": \"<string>\",\n \"disconnection_reason\": \"<string>\",\n \"is_retry\": true\n}"
response = http.request(request)
puts response.read_body{
"error": false,
"message": "Followup created successfully",
"data": {
"id": "abc123def456",
"debt_id": "xyz789ghi012",
"status": "scheduled",
"type": "call",
"call_date": null,
"scheduled_at": "2024-01-25T10:00:00+00:00",
"summary": "Follow-up call to discuss payment plan",
"notes": "Customer previously expressed interest in monthly payment schedule",
"call_id": null,
"audio_url": null,
"pdf_url": null,
"duration_ms": null,
"disconnection_reason": null,
"direction": null,
"phone_number_used": null,
"is_retry": false,
"processed_at": "2024-01-22T15:30:00+00:00"
}
}
Overview
This endpoint allows you to create a new followup activity for an existing debt. You can log calls, emails, SMS, or other communication activities.Authentication
Requires a valid OAuth 2.0 access token with thefollowups:write scope.
Request
string
required
Bearer token for authentication
string
required
Must be
application/jsonRequest Body
string
required
Encrypted ID of the debt this followup belongs to
string
Type of followup:
call, email, sms, whatsapp, voicemail, manual_call, physical, postmailstring
Followup status. Use simple string values:
on_hold, scheduled, in_progress, sent, delivered, deal_found, no_answer, deal_not_found, bad_behavior, failed, cancelled. Defaults to on_hold.string
When the followup was executed (ISO 8601 format)
string
When to execute the followup (ISO 8601 format)
string
Brief summary of the followup
string
Detailed notes about the followup
string
External call ID from the provider
string
URL to the call recording
integer
Duration in milliseconds (for calls)
string
Phone number used for the followup
string
Call direction:
inbound or outboundstring
Reason for call disconnection
boolean
Whether this is a retry attempt
Example Request
curl -X POST "/external-api/v1/followups" \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"debt_id": "xyz789ghi012",
"type": "call",
"status": "scheduled",
"scheduled_at": "2024-01-25T10:00:00Z",
"summary": "Follow-up call to discuss payment plan",
"notes": "Customer previously expressed interest in monthly payment schedule"
}'
const followupData = {
debt_id: 'xyz789ghi012',
type: 'call',
status: 'scheduled',
scheduled_at: '2024-01-25T10:00:00Z',
summary: 'Follow-up call to discuss payment plan',
notes: 'Customer previously expressed interest in monthly payment schedule'
};
const response = await fetch('/external-api/v1/followups', {
method: 'POST',
headers: {
'Authorization': 'Bearer YOUR_ACCESS_TOKEN',
'Content-Type': 'application/json'
},
body: JSON.stringify(followupData)
});
const result = await response.json();
Response
boolean
Always
false for successful requestsstring
Success message
object
The created followup object
Show followup object
Show followup object
string
Encrypted followup identifier
string
Encrypted debt identifier
string
Current followup status
string
Type of followup
string
When the followup was executed (ISO 8601 format)
string
Scheduled execution time (ISO 8601 format)
string
Brief summary
string
Detailed notes
string
External call ID
string
URL to the call recording
string
URL to any associated PDF document
integer
Duration in milliseconds
string
Reason for call disconnection
string
Call direction
string
Phone number used
boolean
Whether this is a retry attempt
string
Processing timestamp (ISO 8601 format)
Success Response
{
"error": false,
"message": "Followup created successfully",
"data": {
"id": "abc123def456",
"debt_id": "xyz789ghi012",
"status": "scheduled",
"type": "call",
"call_date": null,
"scheduled_at": "2024-01-25T10:00:00+00:00",
"summary": "Follow-up call to discuss payment plan",
"notes": "Customer previously expressed interest in monthly payment schedule",
"call_id": null,
"audio_url": null,
"pdf_url": null,
"duration_ms": null,
"disconnection_reason": null,
"direction": null,
"phone_number_used": null,
"is_retry": false,
"processed_at": "2024-01-22T15:30:00+00:00"
}
}
Validation Rules
Required Fields
Required Fields
debt_id: Must be a valid encrypted debt ID that belongs to your company
Type Validation
Type Validation
type: Must be one of:call,sms,email,whatsapp,voicemail,manual_call,physical,postmail
Status Validation
Status Validation
status: Must be one of:on_hold,scheduled,in_progress,sent,delivered,deal_found,no_answer,deal_not_found,bad_behavior,failed,cancelled- Default is
on_holdif not specified
Date Validation
Date Validation
scheduled_at: Must be in ISO 8601 format if providedcall_date: Must be in ISO 8601 format if provided
Error Responses
{
"error": true,
"message": "Validation failed",
"code": 400,
"details": {
"debt_id": "Debt ID is required",
"type": "Invalid followup type. Valid types are: call, sms, email, whatsapp, voicemail, manual_call, physical, postmail"
}
}
{
"error": true,
"message": "Access denied to this debt",
"code": 403
}
{
"error": true,
"message": "Debt not found",
"code": 404
}
After Creation
Once a followup is created, you can:- Monitor Progress: Use Get Followup to check status
- Update Details: Use Update Followup to modify information
- Track Results: View completion status and outcomes
- Generate Reports: Include followup data in your analytics
Related Endpoints
- List Followups - Get all followups
- Get Followup - Get specific followup details
- Update Followup - Modify followup information
- Get Debt - Get the associated debt information