Customers
Customer credit statement
A customer’s consolidated account-credit statement: spendable balance, grants, and draw-down history.
GET
/
v1
/
customers
/
{id}
/
credit-statement
Customer account-credit statement
curl --request GET \
--url https://billing.example.com/v1/customers/{id}/credit-statement \
--header 'Authorization: Bearer <token>'import requests
url = "https://billing.example.com/v1/customers/{id}/credit-statement"
headers = {"Authorization": "Bearer <token>"}
response = requests.get(url, headers=headers)
print(response.text)const options = {method: 'GET', headers: {Authorization: 'Bearer <token>'}};
fetch('https://billing.example.com/v1/customers/{id}/credit-statement', 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://billing.example.com/v1/customers/{id}/credit-statement",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://billing.example.com/v1/customers/{id}/credit-statement"
req, _ := http.NewRequest("GET", url, nil)
req.Header.Add("Authorization", "Bearer <token>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.get("https://billing.example.com/v1/customers/{id}/credit-statement")
.header("Authorization", "Bearer <token>")
.asString();require 'uri'
require 'net/http'
url = URI("https://billing.example.com/v1/customers/{id}/credit-statement")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Get.new(url)
request["Authorization"] = 'Bearer <token>'
response = http.request(request)
puts response.read_body{
"data": {
"customer_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"balances": [
{
"currency": "<string>",
"entity_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"balance": 123
}
],
"grants": [
{
"id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"tenant_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"customer_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"invoice_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"entity_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"reference": "<string>",
"amount": 123,
"subtotal": 123,
"tax_amount": 123,
"igst_amount": 123,
"cgst_amount": 123,
"sgst_amount": 123,
"tax_type": "<string>",
"hsn_code": "<string>",
"balance": 123,
"currency": "<string>",
"status": "issued",
"reason": "<string>",
"expires_at": "2023-11-07T05:31:56Z",
"created_at": "2023-11-07T05:31:56Z",
"updated_at": "2023-11-07T05:31:56Z",
"customer": {
"id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"tenant_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"email": "jsmith@example.com",
"name": "<string>",
"phone": "<string>",
"tax_id": "<string>",
"billing_address": {
"line1": "<string>",
"line2": "<string>",
"postal_code": "<string>",
"city": "<string>",
"state": "<string>",
"zip": "<string>",
"country": "<string>"
},
"ledger_account_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"gstin": "<string>",
"tax_type": "<string>",
"place_of_supply": "<string>",
"tax_exempt": true,
"tax_exemption_number": "<string>",
"tax_exemption_code": "<string>",
"tax_exemption_expires_at": "2023-12-25",
"referral_code": "<string>",
"risk_score": 50,
"risk_factors": {},
"card_brand": "<string>",
"card_last4": "<string>",
"card_exp_month": 123,
"card_exp_year": 123,
"card_token_id": "<string>",
"card_fingerprint": "<string>",
"created_at": "2023-11-07T05:31:56Z"
}
}
],
"applications": [
{
"credit_note_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"invoice_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"invoice_number": "<string>",
"currency": "<string>",
"amount": 123,
"created_at": "2023-11-07T05:31:56Z"
}
],
"summary": [
{
"currency": "<string>",
"total_issued": 123,
"total_applied": 123,
"current_balance": 123
}
]
}
}{
"error": {
"code": "validation_failed",
"message": "<string>"
}
}{
"error": {
"code": "validation_failed",
"message": "<string>"
}
}What it returns
A single, reconciled view of a customer’s account credit:balances— spendable balance per currency (and legal entity). This equals exactly what the billing engine can apply to invoices: adjustment credits with statusissuedand a positive balance.grants— every credit note for the customer (including fully-drawnused,expired, andrefundnotes), newest first.applications— the draw-down history: which credit note settled which invoice, for how much, and when.summary— a per-currency rollup of total issued, total applied, and the current spendable balance.
Example request
curl https://api.recurso.dev/v1/customers/cust_abc123/credit-statement \
-H "Authorization: Bearer $API_KEY"
Example response
{
"data": {
"customer_id": "cust_abc123",
"balances": [
{ "currency": "USD", "entity_id": null, "balance": 4500 }
],
"grants": [
{
"id": "cn_r4t8w1",
"type": "adjustment",
"status": "issued",
"amount": 5000,
"balance": 4500,
"currency": "USD",
"reason": "Goodwill credit",
"expires_at": "2026-12-31T23:59:59Z",
"created_at": "2026-06-01T10:00:00Z"
}
],
"applications": [
{
"credit_note_id": "cn_r4t8w1",
"invoice_id": "inv_001",
"invoice_number": "REC/2026/0042",
"currency": "USD",
"amount": 500,
"created_at": "2026-07-01T09:00:00Z"
}
],
"summary": [
{ "currency": "USD", "total_issued": 5000, "total_applied": 500, "current_balance": 4500 }
]
}
}
The statement’s spendable balance is computed the same way the billing engine
selects credit to apply, so it can never disagree with what the customer can
actually spend. It reconciles to the Customer Credit (2300) ledger account.
⌘I
Customer account-credit statement
curl --request GET \
--url https://billing.example.com/v1/customers/{id}/credit-statement \
--header 'Authorization: Bearer <token>'import requests
url = "https://billing.example.com/v1/customers/{id}/credit-statement"
headers = {"Authorization": "Bearer <token>"}
response = requests.get(url, headers=headers)
print(response.text)const options = {method: 'GET', headers: {Authorization: 'Bearer <token>'}};
fetch('https://billing.example.com/v1/customers/{id}/credit-statement', 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://billing.example.com/v1/customers/{id}/credit-statement",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://billing.example.com/v1/customers/{id}/credit-statement"
req, _ := http.NewRequest("GET", url, nil)
req.Header.Add("Authorization", "Bearer <token>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.get("https://billing.example.com/v1/customers/{id}/credit-statement")
.header("Authorization", "Bearer <token>")
.asString();require 'uri'
require 'net/http'
url = URI("https://billing.example.com/v1/customers/{id}/credit-statement")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Get.new(url)
request["Authorization"] = 'Bearer <token>'
response = http.request(request)
puts response.read_body{
"data": {
"customer_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"balances": [
{
"currency": "<string>",
"entity_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"balance": 123
}
],
"grants": [
{
"id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"tenant_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"customer_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"invoice_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"entity_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"reference": "<string>",
"amount": 123,
"subtotal": 123,
"tax_amount": 123,
"igst_amount": 123,
"cgst_amount": 123,
"sgst_amount": 123,
"tax_type": "<string>",
"hsn_code": "<string>",
"balance": 123,
"currency": "<string>",
"status": "issued",
"reason": "<string>",
"expires_at": "2023-11-07T05:31:56Z",
"created_at": "2023-11-07T05:31:56Z",
"updated_at": "2023-11-07T05:31:56Z",
"customer": {
"id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"tenant_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"email": "jsmith@example.com",
"name": "<string>",
"phone": "<string>",
"tax_id": "<string>",
"billing_address": {
"line1": "<string>",
"line2": "<string>",
"postal_code": "<string>",
"city": "<string>",
"state": "<string>",
"zip": "<string>",
"country": "<string>"
},
"ledger_account_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"gstin": "<string>",
"tax_type": "<string>",
"place_of_supply": "<string>",
"tax_exempt": true,
"tax_exemption_number": "<string>",
"tax_exemption_code": "<string>",
"tax_exemption_expires_at": "2023-12-25",
"referral_code": "<string>",
"risk_score": 50,
"risk_factors": {},
"card_brand": "<string>",
"card_last4": "<string>",
"card_exp_month": 123,
"card_exp_year": 123,
"card_token_id": "<string>",
"card_fingerprint": "<string>",
"created_at": "2023-11-07T05:31:56Z"
}
}
],
"applications": [
{
"credit_note_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"invoice_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"invoice_number": "<string>",
"currency": "<string>",
"amount": 123,
"created_at": "2023-11-07T05:31:56Z"
}
],
"summary": [
{
"currency": "<string>",
"total_issued": 123,
"total_applied": 123,
"current_balance": 123
}
]
}
}{
"error": {
"code": "validation_failed",
"message": "<string>"
}
}{
"error": {
"code": "validation_failed",
"message": "<string>"
}
}