Cash Records
The six endpoints that keep an installation's income and expense book.
Overview
The cash book holds an installation's income and expenses. Two kinds of record sit in it together: the ones invoices open by themselves once paid, and the ones an operator enters by hand.
The system mark tells them apart. A record from an invoice is a reflection: it cannot be changed or removed, because its source is the invoice itself. Records entered by hand can be edited.
The summary gives this month's income, expenses and the difference between them. Amounts in other currencies are converted into the local one before adding.
Reference
Listing the Records
Returns the income and expense records, filtered.
income, expense.curl 'https://panel.example.com/api/v1/admin/invoices/cash?type=expense' \
-H "Authorization: Bearer $API_KEY"const url = new URL('https://panel.example.com/api/v1/admin/invoices/cash');
url.searchParams.set('type', 'expense');
const res = await fetch(url, {
headers: { Authorization: `Bearer ${apiKey}` },
});
const body = await res.json();$ch = curl_init('https://panel.example.com/api/v1/admin/invoices/cash?' . http_build_query(['type' => 'expense']));
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $apiKey],
]);
$body = json_decode(curl_exec($ch), true);
curl_close($ch);// The list carries records FROM INVOICES too; filter on the system mark for hand-entered ones.
$manual = array_filter(
Api::Invoices()->GetCashEntries()['data'],
fn ($e) => ! $e['is_system'],
);Adding a Record
Puts an income or expense record into the book by hand.
income, expense.curl -X POST 'https://panel.example.com/api/v1/admin/invoices/cash' \
-H "Authorization: Bearer $API_KEY" \
-H 'Content-Type: application/json' \
-d '{"type":"expense","currency_id":840,"amount":49.9,"description":"Sunucu gideri"}'const res = await fetch('https://panel.example.com/api/v1/admin/invoices/cash', {
method: 'POST',
headers: {
Authorization: `Bearer ${apiKey}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
type: 'expense',
currency_id: 840,
amount: 49.9,
description: 'Server cost',
}),
});
const body = await res.json();$ch = curl_init('https://panel.example.com/api/v1/admin/invoices/cash');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_POST => true,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ' . $apiKey,
'Content-Type: application/json',
],
CURLOPT_POSTFIELDS => json_encode([
'type' => 'expense',
'currency_id' => 840,
'amount' => 49.9,
'description' => 'Server cost',
]),
]);
$body = json_decode(curl_exec($ch), true);
curl_close($ch);// A hand-entered record IS NOT TIED to an invoice; those only come from the payment flow.
Api::Invoices()->CreateCashEntry([
'type' => 'expense',
'currency_id' => 840,
'amount' => 49.9,
]);Reading the Cash Summary
Returns this month's income, expenses and balance.
curl 'https://panel.example.com/api/v1/admin/invoices/cash/summary' \
-H "Authorization: Bearer $API_KEY"const res = await fetch('https://panel.example.com/api/v1/admin/invoices/cash/summary', {
headers: { Authorization: `Bearer ${apiKey}` },
});
const body = await res.json();$ch = curl_init('https://panel.example.com/api/v1/admin/invoices/cash/summary');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $apiKey],
]);
$body = json_decode(curl_exec($ch), true);
curl_close($ch);// The summary is ALWAYS this month; for another period pull the list by date and add it up.
$sum = Api::Invoices()->GetCashSummary()['data'];Reading One Record
Returns a single cash record.
income, expense.curl 'https://panel.example.com/api/v1/admin/invoices/cash/51' \
-H "Authorization: Bearer $API_KEY"const res = await fetch(`https://panel.example.com/api/v1/admin/invoices/cash/${cashId}`, {
headers: { Authorization: `Bearer ${apiKey}` },
});
const body = await res.json();$ch = curl_init('https://panel.example.com/api/v1/admin/invoices/cash/' . $cashId);
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $apiKey],
]);
$body = json_decode(curl_exec($ch), true);
curl_close($ch);// The client details DO NOT arrive here; that field is filled by the list join alone.
$entry = Api::Invoices()->GetCashEntry(['cash_id' => $cashId])['data'];Updating a Record
Changes a cash record entered by hand.
curl -X PATCH 'https://panel.example.com/api/v1/admin/invoices/cash/51' \
-H "Authorization: Bearer $API_KEY" \
-H 'Content-Type: application/json' \
-d '{"amount":59.9,"description":"Sunucu gideri (guncellendi)"}'const res = await fetch(`https://panel.example.com/api/v1/admin/invoices/cash/${cashId}`, {
method: 'PATCH',
headers: {
Authorization: `Bearer ${apiKey}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({ amount: 59.9, description: 'Server cost (updated)' }),
});
const body = await res.json();$ch = curl_init('https://panel.example.com/api/v1/admin/invoices/cash/' . $cashId);
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_CUSTOMREQUEST => 'PATCH',
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ' . $apiKey,
'Content-Type: application/json',
],
CURLOPT_POSTFIELDS => json_encode(['amount' => 59.9]),
]);
$body = json_decode(curl_exec($ch), true);
curl_close($ch);// A record marked as system gives a 422; in a bulk fix, filter on that field first.
$entry = Api::Invoices()->GetCashEntry(['cash_id' => $cashId])['data'];
if (! $entry['is_system'])
Api::Invoices()->UpdateCashEntry(['cash_id' => $cashId, 'amount' => 59.9]);Removing a Record
Removes a cash record entered by hand.
curl -X DELETE 'https://panel.example.com/api/v1/admin/invoices/cash/52' \
-H "Authorization: Bearer $API_KEY"const res = await fetch(`https://panel.example.com/api/v1/admin/invoices/cash/${cashId}`, {
method: 'DELETE',
headers: { Authorization: `Bearer ${apiKey}` },
});
const body = await res.json();$ch = curl_init('https://panel.example.com/api/v1/admin/invoices/cash/' . $cashId);
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_CUSTOMREQUEST => 'DELETE',
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $apiKey],
]);
$body = json_decode(curl_exec($ch), true);
curl_close($ch);// A record from an invoice is removed on the INVOICE side; it cannot go from here.
Api::Invoices()->DeleteCashEntry(['cash_id' => $cashId]);Pitfalls
A cash record tied to an invoice is read-only: the update and delete calls are refused. That is deliberate, because the record reflects the invoice and cannot contradict it. To correct an amount, go back to the invoice and the cash record follows.
The listing returns hand-entered records and invoice ones together, with no filter to separate them. To add up only the hand-entered expenses in a report, sift on the system mark yourself; otherwise invoice income lands in the sum.
The summary takes no period and always gives the month you are in. For last month or a quarter, pull the list by date and add it up yourself. You also have to handle the currency conversion, because the list does not arrive converted the way the summary does.
The client on the linked invoice arrives in the list alone, and reading one record leaves that field empty. The list performs a join and the detail does not. To get the client for a single record, read the invoice from its number.
The create endpoint always opens a standalone record, and no invoice number ties one to an invoice. Records with that link come from the payment flow alone. So entering income by hand and also marking the same invoice paid shows the same money twice in the book.
Related Articles
Thanks for your feedback!
Our support team is here around the clock for anything you can't find above.