Invoice Status and Notices
The five endpoints for an invoice's status, its client details and the notices sent.
Overview
These five endpoints run the life of an invoice once issued. They change its status, correct the client details, send a notice, formalise it and remind.
The status change is the heaviest thing here. Marking an invoice paid opens an income entry, gives it a paid-invoice number and sets the linked services moving; refunding winds that back and can order a refund through the payment module.
Three of the endpoints mail the client: the notice, the reminder and, when its file is there, formalising. Calling them from a script reaches real people.
Reference
Changing the Status
Changes an invoice's status and carries out what that status brings.
paid, unpaid, refund or cancelled.curl -X PUT 'https://panel.example.com/api/v1/admin/invoices/1212/status' \
-H "Authorization: Bearer $API_KEY" \
-H 'Content-Type: application/json' \
-d '{"status":"paid","payment_method":"Balance","notify":true}'const res = await fetch(`https://panel.example.com/api/v1/admin/invoices/${id}/status`, {
method: 'PUT',
headers: {
Authorization: `Bearer ${apiKey}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
status: 'paid',
payment_method: 'Balance',
notify: true,
}),
});
const body = await res.json();$ch = curl_init('https://panel.example.com/api/v1/admin/invoices/' . $id . '/status');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_CUSTOMREQUEST => 'PUT',
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ' . $apiKey,
'Content-Type: application/json',
],
CURLOPT_POSTFIELDS => json_encode([
'status' => 'paid',
'payment_method' => 'Balance',
'notify' => true,
]),
]);
$body = json_decode(curl_exec($ch), true);
curl_close($ch);// Marking it paid OPENS AN INCOME ENTRY, gives a number and sets the services moving.
Api::Invoices()->UpdateInvoiceStatus([
'id' => $id,
'status' => 'paid',
'notify' => true,
]);Correcting the Client Details
Corrects the client and address details frozen onto an invoice.
curl -X PATCH 'https://panel.example.com/api/v1/admin/invoices/1212/client-details' \
-H "Authorization: Bearer $API_KEY" \
-H 'Content-Type: application/json' \
-d '{"kind":"corporate","company_name":"Ornek A.S.","tax_number":"0000000000"}'const res = await fetch(`https://panel.example.com/api/v1/admin/invoices/${id}/client-details`, {
method: 'PATCH',
headers: {
Authorization: `Bearer ${apiKey}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
kind: 'corporate',
company_name: 'Example Inc.',
tax_number: '000000000',
address: { detail: '123 Market Street', country_id: 840, zipcode: '94105' },
}),
});
const body = await res.json();$ch = curl_init('https://panel.example.com/api/v1/admin/invoices/' . $id . '/client-details');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_CUSTOMREQUEST => 'PATCH',
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ' . $apiKey,
'Content-Type: application/json',
],
CURLOPT_POSTFIELDS => json_encode([
'kind' => 'corporate',
'company_name' => 'Example Inc.',
'tax_number' => '000000000',
]),
]);
$body = json_decode(curl_exec($ch), true);
curl_close($ch);// This endpoint DOES NOT TOUCH the live client; it corrects the copy on this invoice.
Api::Invoices()->UpdateInvoiceClientDetails([
'id' => $id,
'company_name' => 'Example Inc.',
]);Sending a Notice
Sends the client the invoice notice template you pick.
curl -X POST 'https://panel.example.com/api/v1/admin/invoices/1231/notifications' \
-H "Authorization: Bearer $API_KEY" \
-H 'Content-Type: application/json' \
-d '{"template":"invoice-created"}'const res = await fetch(`https://panel.example.com/api/v1/admin/invoices/${id}/notifications`, {
method: 'POST',
headers: {
Authorization: `Bearer ${apiKey}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({ template: 'invoice-created' }),
});
const body = await res.json();$ch = curl_init('https://panel.example.com/api/v1/admin/invoices/' . $id . '/notifications');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_POST => true,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ' . $apiKey,
'Content-Type: application/json',
],
CURLOPT_POSTFIELDS => json_encode(['template' => 'invoice-created']),
]);
$body = json_decode(curl_exec($ch), true);
curl_close($ch);// A switched-off template gives a 422; the list on screen does not mark which are on.
Api::Invoices()->SendInvoiceNotification([
'id' => $id,
'template' => 'invoice-created',
]);Formalising an Invoice
Turns an invoice into a formal one.
curl -X POST 'https://panel.example.com/api/v1/admin/invoices/1231/formalize' \
-H "Authorization: Bearer $API_KEY" \
-H 'Content-Type: application/json' \
-d '{"notify":false}'const res = await fetch(`https://panel.example.com/api/v1/admin/invoices/${id}/formalize`, {
method: 'POST',
headers: {
Authorization: `Bearer ${apiKey}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({ notify: false }),
});
const body = await res.json();$ch = curl_init('https://panel.example.com/api/v1/admin/invoices/' . $id . '/formalize');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_POST => true,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ' . $apiKey,
'Content-Type: application/json',
],
CURLOPT_POSTFIELDS => json_encode(['notify' => false]),
]);
$body = json_decode(curl_exec($ch), true);
curl_close($ch);// A second call gives a 422; in a batch script read the invoice's state first.
$inv = Api::Invoices()->GetInvoice(['id' => $id])['data'];
if (! $inv['formalized']) Api::Invoices()->FormalizeInvoice(['id' => $id]);Sending a Reminder
Sends the client a reminder for an unpaid invoice.
invoice-reminder; there is no field to change it with.curl -X POST 'https://panel.example.com/api/v1/admin/invoices/1231/remind' \
-H "Authorization: Bearer $API_KEY"const res = await fetch(`https://panel.example.com/api/v1/admin/invoices/${id}/remind`, {
method: 'POST',
headers: { Authorization: `Bearer ${apiKey}` },
});
const body = await res.json();$ch = curl_init('https://panel.example.com/api/v1/admin/invoices/' . $id . '/remind');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_POST => true,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $apiKey],
]);
$body = json_decode(curl_exec($ch), true);
curl_close($ch);// The call counts NO ATTEMPTS; it will remind the same invoice again and again.
Api::Invoices()->RemindInvoice(['id' => $id]);Pitfalls
Marking an invoice paid opens an income entry. It also gives the invoice a paid number and sets the linked services moving. Refunding winds all of that back, unwinds the metered rows and can order a refund through the payment module. Do not try this on a real client's invoice.
When the invoice already stands there, the call is refused. The one exception is changing the payment method on a paid invoice, where the status holds and only the method is written. A script that syncs statuses should read the current one first.
This endpoint corrects the frozen copy on the invoice and leaves the live client record alone. A wrong address may need fixing in both places. Correct it here for the document already issued, and on the client for the ones to come. A correction here does not reach other invoices either.
Formalising an invoice that is already formal gives an error. In a batch script that stops the loop at the first one, so read each invoice's state first. A hook can refuse it as well, because on some installations the act has a counterpart in the books.
The reminder endpoint keeps no count of how often it was called, and calling it twice sends the same client two mails. A script that walks the overdue invoices should keep on its own side which invoice was reminded and when. Otherwise every run warns everyone again.
Related Articles
Thanks for your feedback!
Our support team is here around the clock for anything you can't find above.