Contents
On this page

Create Transfer - Plugixa Inventory

POST /plugixa-inventory/v1/transfers

Create a draft transfer that moves stock from one warehouse to another.

The user needs the plugixa_inventory_create capability (administrators have every inventory capability). With Pro Roles and permissions enforcing, their role must also allow creating transfers. Needs Plugixa Inventory Pro with the Warehouse transfers app on in Plugixa Inventory -> App Manager; with it off, this route answers 404.

Request

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

Request body

Content type: application/json

Field Type Required Description
from_warehouse_id integer Yes The live warehouse the stock leaves.
to_warehouse_id integer Yes The live warehouse the stock arrives in. Not the same as from_warehouse_id.
transfer_date string No YYYY-MM-DD, optionally followed by a time (HH:MM or HH:MM:SS), in the site’s timezone. Defaults to now. It becomes the date of the ledger rows.
reference string No Your own reference, at most 50 characters. Left empty, the document gets TR-YYYY-NNNN (year of the document date, id padded to four digits) when it is finalized.
details string No HTML. Becomes the reason on the ledger rows.
assigned_user_id integer No A WordPress user id. Not checked.
lines array No The lines. See below.

Lines

Field Type Required Description
item_id integer Yes The item. Checked when the document is finalized, not before.
quantity number Yes Greater than zero. Always positive: the document type decides the direction.
unit_id integer No The unit the quantity is in PRO.
cost_per_unit number No Not negative. Defaults to 0. The costing method can replace it when the document is finalized.
notes string No Plain text.

Lines with neither an item nor a quantity are skipped. Lines are kept in the order sent, numbered from 1 in position. A new document is always a draft: a status you send is ignored. Nothing reaches stock until you finalize it. If a line is refused, nothing is saved.

{
  "from_warehouse_id": 1,
  "to_warehouse_id": 2,
  "lines": [
    {
      "item_id": 42,
      "quantity": 40
    }
  ]
}

Responses

201 Created. data is the new draft with its lines.

{
  "success": true,
  "data": {
    "id": 12,
    "reference": "",
    "from_warehouse_id": 1,
    "to_warehouse_id": 2,
    "transfer_date": "2026-11-12 10:30:00",
    "status": "draft",
    "finalized_at": null,
    "finalized_by": null,
    "batch_id": "",
    "line_count": 1,
    "total_quantity": 0.0,
    "total_cost": 0.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 09:30: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": 0.0,
        "out_transaction_id": 0,
        "in_transaction_id": 0,
        "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
      }
    ],
    "from_warehouse_name": "Main warehouse",
    "to_warehouse_name": "Shop floor"
  }
}
Field Type Meaning
data.id integer The transfer’s id
data.status string draft or finalized
data.transfer_date string Document date, in the site’s timezone
data.from_warehouse_name string|null The source warehouse’s name
data.to_warehouse_name string|null The destination warehouse’s name
data.lines[].out_transaction_id integer The ledger row taking stock out. 0 until finalized
data.lines[].in_transaction_id integer The ledger row putting it in. 0 until finalized

Errors

Status Code When
422 plugixa_inventory_invalid_date transfer_date is not a real date in the accepted form.
422 plugixa_inventory_missing_warehouse A warehouse is missing. data.field names it.
422 plugixa_inventory_same_warehouse Both warehouses are the same.
422 plugixa_inventory_unknown_warehouse A warehouse is not live. data.field names it.
422 plugixa_inventory_too_long A text field is longer than its column. data.field names it and data.max gives the limit.
422 plugixa_inventory_line_needs_item A line has a quantity but no item_id.
422 plugixa_inventory_line_needs_quantity A line has an item_id but no quantity above zero. data.item_id names it.
422 plugixa_inventory_not_a_number A line’s number is not a number. data.line (from 1) and data.item_id say which.
422 plugixa_inventory_negative_number A line’s cost_per_unit (or weight) is negative.
500 plugixa_inventory_insert_failed The database refused to save the transfer.

Plus the errors every endpoint can return.

Examples

curl -s -X POST "https://your-site.example/wp-json/plugixa-inventory/v1/transfers" \
  -u "admin:$WP_APP_PASSWORD" \
  -H "Content-Type: application/json" \
  -d '{"from_warehouse_id":1,"to_warehouse_id":2,"lines":[{"item_id":42,"quantity":40}]}'
<?php
$ch = curl_init('https://your-site.example/wp-json/plugixa-inventory/v1/transfers');
curl_setopt_array($ch, [
    CURLOPT_CUSTOMREQUEST  => 'POST',
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_USERPWD        => 'admin:' . getenv('WP_APP_PASSWORD'),
    CURLOPT_HTTPHEADER     => ['Content-Type: application/json'],
    CURLOPT_POSTFIELDS     => json_encode([
        'from_warehouse_id' => 1,
        'to_warehouse_id'   => 2,
        'lines'             => [
            [
                'item_id'  => 42,
                'quantity' => 40,
            ],
        ],
    ]),
]);
$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', {
  method: 'POST',
  headers: { 'Authorization': auth, 'Content-Type': 'application/json' },
  body: JSON.stringify({
    from_warehouse_id: 1,
    to_warehouse_id: 2,
    lines: [
      {
        item_id: 42,
        quantity: 40,
      },
    ],
  }),
});
const { data } = await response.json();

Quick Links

Share