Order Records
The six endpoints that read, move and remove orders already placed.
Overview
An order is the record of a purchase and a service is the thing born from it. The two live apart: removing an order does not kill the service, and closing a service does not change the order.
The detail endpoint shows that split plainly. The lines are the order's own and do not move, while the service list comes back live on every read, its states taken from the service record.
Tax and discounts are kept the same way: the rates from order time are frozen inside the record. Working them out again at today's setting misreads a past bill.
Reference
Listing the Orders
Returns the orders page by page, with the client and invoice summary.
curl 'https://panel.example.com/api/v1/admin/orders?status=waiting&limit=50' \
-H "Authorization: Bearer $API_KEY"const res = await fetch('https://panel.example.com/api/v1/admin/orders?status=waiting', {
headers: { Authorization: `Bearer ${apiKey}` },
});
const { data, meta } = await res.json();
const unpaid = data.filter((o) => o.invoice_status === 'unpaid');$ch = curl_init('https://panel.example.com/api/v1/admin/orders?status=waiting');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $apiKey],
]);
$body = json_decode(curl_exec($ch), true);
curl_close($ch);// A listed order HAS the amount and NOT the lines: lines and services come on the detail endpoint alone.
$rows = Api::Orders()->GetOrders([], ['status' => 'waiting'])['data'];
foreach ($rows as $o) $detail[$o['id']] = Api::Orders()->GetOrder(['id' => $o['id']])['data'];Reading an Order in Full
Returns an order's tax, discounts, lines and the services it brought into being.
curl 'https://panel.example.com/api/v1/admin/orders/92' \
-H "Authorization: Bearer $API_KEY"const res = await fetch(`https://panel.example.com/api/v1/admin/orders/${id}`, {
headers: { Authorization: `Bearer ${apiKey}` },
});
const { data } = await res.json();
const live = data.services.filter((s) => s.exists);$ch = curl_init('https://panel.example.com/api/v1/admin/orders/' . $id);
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $apiKey],
]);
$body = json_decode(curl_exec($ch), true);
curl_close($ch);// The tax and discount are a snapshot of ORDER TIME; do not work them out again at today's rate.
$o = Api::Orders()->GetOrder(['id' => $id])['data'];
$rateThen = $o['taxes']['rate'] ?? 0;Updating the Order Envelope
Changes an order's note and which partner is credited.
curl -X PATCH 'https://panel.example.com/api/v1/admin/orders/92' \
-H "Authorization: Bearer $API_KEY" \
-H 'Content-Type: application/json' \
-d '{"notes":"Expedite provisioning","affiliate_id":5}'const res = await fetch(`https://panel.example.com/api/v1/admin/orders/${id}`, {
method: 'PATCH',
headers: {
Authorization: `Bearer ${apiKey}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({ notes: 'Expedite provisioning' }),
});
const body = await res.json();$ch = curl_init('https://panel.example.com/api/v1/admin/orders/' . $id);
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_CUSTOMREQUEST => 'PATCH',
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ' . $apiKey,
'Content-Type: application/json',
],
CURLOPT_POSTFIELDS => json_encode(['notes' => $note]),
]);
$body = json_decode(curl_exec($ch), true);
curl_close($ch);// The note and the partner change alone; lines, prices and the client CANNOT be edited here.
Api::Orders()->UpdateOrder(['id' => $id, 'notes' => $note, 'affiliate_id' => $aff]);Changing the Order State
Changes an order's state and carries it through to its services.
curl -X PUT 'https://panel.example.com/api/v1/admin/orders/92/status' \
-H "Authorization: Bearer $API_KEY" \
-H 'Content-Type: application/json' \
-d '{"status":"active","apply_on_module":false}'const res = await fetch(`https://panel.example.com/api/v1/admin/orders/${id}/status`, {
method: 'PUT',
headers: {
Authorization: `Bearer ${apiKey}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({ status: 'active', apply_on_module: false }),
});
const { data } = await res.json();
if (data.services_updated) refreshServices();$ch = curl_init('https://panel.example.com/api/v1/admin/orders/' . $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' => 'active', 'apply_on_module' => false]),
]);
$body = json_decode(curl_exec($ch), true);
curl_close($ch);// apply_on_module starts real work AT THE PROVIDER: active builds and cancelled shuts down. Leave it false first.
Api::Orders()->UpdateOrderStatus([
'id' => $id, 'status' => 'active', 'apply_on_module' => false,
]);Removing an Order
Removes the order record while the services it made stay where they are.
curl -X DELETE 'https://panel.example.com/api/v1/admin/orders/92' \
-H "Authorization: Bearer $API_KEY"const res = await fetch(`https://panel.example.com/api/v1/admin/orders/${id}`, {
method: 'DELETE',
headers: { Authorization: `Bearer ${apiKey}` },
});
const body = await res.json();$ch = curl_init('https://panel.example.com/api/v1/admin/orders/' . $id);
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);// The services ARE NOT removed: the order goes, they stay, and which order made them is lost.
$o = Api::Orders()->GetOrder(['id' => $id])['data'];
foreach ($o['services'] as $s) if ($s['exists']) $orphans[] = $s['id'];
Api::Orders()->DeleteOrder(['id' => $id]);Removing One of an Order's Services
Removes a service the order brought into being.
curl -X DELETE 'https://panel.example.com/api/v1/admin/orders/92/services/561' \
-H "Authorization: Bearer $API_KEY" \
-H 'Content-Type: application/json' \
-d '{"apply_on_module":false}'const res = await fetch(`https://panel.example.com/api/v1/admin/orders/${id}/services/${sid}`, {
method: 'DELETE',
headers: {
Authorization: `Bearer ${apiKey}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({ apply_on_module: false }),
});
const body = await res.json();$ch = curl_init('https://panel.example.com/api/v1/admin/orders/' . $id . '/services/' . $sid);
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_CUSTOMREQUEST => 'DELETE',
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ' . $apiKey,
'Content-Type: application/json',
],
CURLOPT_POSTFIELDS => json_encode(['apply_on_module' => false]),
]);
$body = json_decode(curl_exec($ch), true);
curl_close($ch);// A service belonging to another order gives 404; take the id from the service list in the detail.
$o = Api::Orders()->GetOrder(['id' => $id])['data'];
$mine = array_column($o['services'], 'id');
if (in_array($sid, $mine, true))
Api::Orders()->DeleteOrderService(['id' => $id, 'sid' => $sid, 'apply_on_module' => false]);Pitfalls
The order record goes and the services it made stay where they are, still billing. The one link left breaks as well: which order made a service can no longer be traced. Remove the services first when you mean to undo a purchase entirely.
Turning on the provider option during a state change starts real work on the server: active builds and cancelled shuts an account down. Leaving it on during a bulk correction reaches client servers all at once. Try it off first and look at the result.
The tax rate, the additional taxes and the coupon discount in the detail were worked out at order time and stand that way in the record. Two figures disagree when today's tax setting has moved, and that is historical accuracy rather than a fault. Use the record's own rate in a report.
The update endpoint writes the note and the partner credit alone. Lines, quantities, prices, cycles and the client cannot be changed here. The way to handle an order built wrong is to cancel it and build another rather than to edit it.
The service removal endpoint checks that the service truly belongs to that order, and one from another order gets 404. That gate stops a wrong id from removing the wrong service. Take the id from the list in the detail.
The listing gives a summary for each order: the amount, how many lines and the client. The lines themselves, the answers to the questions and the services born come on the detail endpoint. Showing lines in a listing screen means one more call per row.
Related Articles
Thanks for your feedback!
Our support team is here around the clock for anything you can't find above.