Contents
On this page

Finalize Transfer - Plugixa Inventory

POST /plugixa-inventory/v1/transfers/{id}/finalize

Finalize a draft transfer: stock leaves the source warehouse and arrives in the destination.

The user needs the plugixa_inventory_edit capability (administrators have every inventory capability). With Pro Roles and permissions enforcing, their role must also allow editing this transfer. Needs Plugixa Inventory Pro with the Warehouse transfers app on in Plugixa Inventory -> App Manager; with it off, this route answers 404. Finalizing also needs the plugixa_inventory_manage capability, which any user holding an inventory capability has.

This writes the ledger. Finalizing is the only way stock changes. It is all or nothing, and it cannot be undone: to correct a finalized document, finalize an opposite one.

Each line writes two ledger rows: transfer_out from the source and transfer_in into the destination. The item’s total on hand does not change. total_quantity and total_cost count the outgoing side once.

Request

POST https://your-site.example/wp-json/plugixa-inventory/v1/transfers/12/finalize

Path parameters

Name Type Description
id integer The transfer’s id

Responses

200 OK. data is the finalized transfer with its lines.

{
  "success": true,
  "data": {
    "id": 12,
    "reference": "TR-2026-0012",
    "from_warehouse_id": 1,
    "to_warehouse_id": 2,
    "transfer_date": "2026-11-12 10:30:00",
    "status": "finalized",
    "finalized_at": "2026-11-12 10:15:00",
    "finalized_by": 1,
    "batch_id": "3f6c1a52-8d0e-4b7a-9c61-2f4e8a9b7d10",
    "line_count": 1,
    "total_quantity": 40.0,
    "total_cost": 168.0,
    "details": "",
    "attachments": null,
    "assigned_user_id": null,
    "created_by": 1,
    "modified_by": 1,
    "created_at": "2026-11-12 09:30:00",
    "modified_at": "2026-11-12 10:15:00",
    "deleted_at": null,
    "lines": [
      {
        "id": 77,
        "transfer_id": 12,
        "item_id": 42,
        "unit_id": null,
        "quantity": 40.0,
        "cost_per_unit": 4.2,
        "total_cost": 168.0,
        "out_transaction_id": 990,
        "in_transaction_id": 991,
        "notes": "",
        "position": 1,
        "created_by": "1",
        "modified_by": "1",
        "created_at": "2026-11-12 09:30:00",
        "modified_at": "2026-11-12 09:30:00",
        "deleted_at": null,
        "item_name": "Printer paper A4",
        "item_sku": "PAP-A4",
        "item_type": "consumable",
        "unit_code": null
      }
    ]
  }
}
Field Type Meaning
data.status string finalized
data.reference string Your reference, or TR-YYYY-NNNN
data.batch_id string The id shared by the ledger rows this wrote
data.lines[].out_transaction_id integer The transfer_out ledger row
data.lines[].in_transaction_id integer The transfer_in ledger row

This answer does not carry the warehouse names. Read the document again with Get Transfer for those.

Errors

Status Code When
404 plugixa_inventory_not_found No document with that id, or it is in the trash.
409 plugixa_inventory_invalid_transition The document is already finalized. data.status_now is its status.
422 plugixa_inventory_document_empty The document has no lines.
422 plugixa_inventory_unknown_warehouse The source or destination warehouse no longer exists. data.field names it.
422 plugixa_inventory_invalid_lines A line points at an item that no longer exists. data.lines lists them.
409 plugixa_inventory_insufficient_stock A decrease needs more than the warehouse holds. data.lines lists every short item with item_id, warehouse_id, available and requested.
409 plugixa_inventory_stock_changed There was enough stock when checked, and not any more when written. Nothing was applied: try again.
409 plugixa_inventory_too_many_layers / plugixa_inventory_costing_unavailable The costing method cannot cost a removal. Nothing was applied.
503 plugixa_inventory_stock_busy Another stock operation is running. Try again in a moment.
500 plugixa_inventory_stock_write_failed The stock change could not be written. Nothing was applied.
409 plugixa_inventory_conflict You sent modified_at and the record has changed since. data.expected and data.current carry both values.

Plus the errors every endpoint can return.

Examples

curl -s -X POST "https://your-site.example/wp-json/plugixa-inventory/v1/transfers/12/finalize" \
  -u "admin:$WP_APP_PASSWORD"
<?php
$ch = curl_init('https://your-site.example/wp-json/plugixa-inventory/v1/transfers/12/finalize');
curl_setopt_array($ch, [
    CURLOPT_CUSTOMREQUEST  => 'POST',
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_USERPWD        => 'admin:' . getenv('WP_APP_PASSWORD'),
]);
$response = json_decode(curl_exec($ch), true);
curl_close($ch);
const auth = 'Basic ' + btoa(`admin:${process.env.WP_APP_PASSWORD}`);
const response = await fetch('https://your-site.example/wp-json/plugixa-inventory/v1/transfers/12/finalize', {
  method: 'POST',
  headers: { 'Authorization': auth },
});
const { data } = await response.json();

Quick Links

Share