Skip to content

Orders ​

php
$orders = $console->orders($team);   // a Team or its id

Placing an order ​

php
$order = $console->orders($team)->create([
    ['family' => 'container', 'product_id' => $planId, 'attributes' => [
        'location_id' => 'bon1',
        'container_template_id' => $templateId,
        'vlan_id' => $vlanId,
        'ssh_key' => $sshKeyId,             // optional
        'name' => 'game-1',                 // optional hostname
    ]],
], ['tos_accepted' => true]);               // required: only once your user accepted the terms

return redirect($order->checkout_url);      // the user confirms (and pays) on Anikeen ID
  • $items: 1–10 items, each with family and product_id from the catalog and attributes per family - see Order attributes.
  • $options: tos_accepted (required, true - send it only once your user accepted the terms of service), withdrawal_waiver, coupon_code, return_url.
php
$order = $orders->create($items, [
    'tos_accepted' => true,
    'withdrawal_waiver' => true,
    'coupon_code' => 'SPRING',
]);

The order of your app team is open with a checkout_url: redirect the user there to confirm and pay on Anikeen ID. Nothing is charged before.

Containers with LXC options ​

Containers that run their own containers inside (e.g. rootless Podman) need LXC options. They are allow-listed: features fuse and keyctl, devices tun; nesting is always on, anything else answers 422.

php
use Anikeen\Console\Resources\Container;

$console->orders($team)->create([
    ['family' => 'container', 'product_id' => $gpuPlanId, 'attributes' => [
        'location_id' => 'bon1',
        'container_template_id' => $templateId,
        'vlan_id' => $vlanId,
        'options' => [
            'features' => [Container::FEATURE_FUSE, Container::FEATURE_KEYCTL],
            'devices' => [Container::DEVICE_TUN],
        ],
    ]],
], ['tos_accepted' => true]);

The catalog lists the allowed values in $catalog->options('container')->options. See LXC options.

Back to your app (return_url) ​

Send the user back to your app after the checkout (app tokens only; https, plain http only for localhost). The Console redirects there with the order id and its status appended:

php
$order = $console->orders($team)->create($items, [
    'tos_accepted' => true,
    'return_url' => route('ordered'),   // → https://your.app/ordered?console_order=01JE…&status=completed
]);

// routes/web.php
Route::get('/ordered', function (Request $request) {
    $console = AnikeenConsole::forUser($request->user());
    $team = $console->appTeam();

    // never trust the query: read the order (completed once Anikeen ID confirmed it)
    $order = $console->orders($team)->find($request->query('console_order'));

    return view('ordered', ['order' => $order]);
})->name('ordered');

Idempotency ​

Every create() sends an Idempotency-Key - a new UUID per call - and keeps it for the retry after a token refresh, so an order is never placed twice. The key that was sent is on the order:

php
$order->idempotencyKey;

Use your own key, e.g. the id of your own order, so that a retry after a crash returns the first order:

php
$order = $orders
    ->withIdempotencyKey("myapp-order-{$localOrder->id}")
    ->create($items, ['tos_accepted' => true]);

Keys live 24 hours per team; the same key with another body is refused (ValidationFailedException, error idempotency_key_reused). At most 10 orders per minute and team (RateLimitException). See Idempotency.

Reading orders ​

php
$order = $orders->find($orderId);            // an open order is checked with Anikeen ID first
$order = $order->refresh();                  // GET …/orders/{order} again

$order->status;                              // pending, open, completed, cancelled, expired, failed
$order->isOpen();
$order->isCompleted();
$order->isFinal();                           // completed, cancelled, expired or failed
$order->products();                          // [{type: "container", id: "01JD…"}, …] once provisioned

foreach ($orders->list(['status' => 'open']) as $order) { … }   // newest first; also per_page, page
Property
id, team_id
statuspending, open, completed, cancelled, expired, failed
modesession or direct
sourceapi or console
checkout_urlshown only to the user who ordered, while open
expires_at, error, created_at, completed_at
items{id, family, product_id, product_name, unit, list_price, price, status, product, provisioned_at}

Rather than polling, listen for the OrderCompleted and ProductReady webhook events.

Anikeen Console documentation