Contents
On this page

Create Stock Movement - Plugixa Inventory

POST /plugixa-inventory/v1/stock-movements

Create a draft stock movement: stock in, stock out, or an asset checked in or out.

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 stock movements.

Request

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

Request body

Content type: application/json

Field Type Required Description
movement_type string No check_in, check_out, add_stock (the default) or remove_stock.
warehouse_id integer Yes A live warehouse.
recipient_id integer No A live recipient. Needed to finalize a check_out.
movement_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 SM-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.
weight number No Not negative.
weight_unit string No mg, g, kg, t, oz or lb.
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.

The type decides which items a line may carry, checked when the document is finalized: check_in and check_out take assets only, add_stock and remove_stock take any type. Movement Types returns the same rules.

{
  "movement_type": "add_stock",
  "warehouse_id": 1,
  "movement_date": "2026-11-12 10:30",
  "lines": [
    {
      "item_id": 42,
      "quantity": 120,
      "cost_per_unit": 4.2,
      "notes": "Delivery note 4471"
    }
  ]
}

Responses

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

{
  "success": true,
  "data": {
    "id": 57,
    "reference": "",
    "movement_type": "add_stock",
    "warehouse_id": 1,
    "recipient_id": null,
    "recipient": "",
    "movement_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": 210,
        "movement_id": 57,
        "item_id": 42,
        "unit_id": null,
        "quantity": 120.0,
        "weight": 0.0,
        "weight_unit": "",
        "weight_base": 0.0,
        "cost_per_unit": 4.2,
        "total_cost": 0.0,
        "transaction_id": 0,
        "notes": "Delivery note 4471",
        "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
      }
    ],
    "warehouse_name": "Main warehouse",
    "recipient_name": null
  }
}
Field Type Meaning
data.id integer The document’s id
data.reference string Your reference, empty until finalized when you gave none
data.status string draft or finalized
data.movement_date string Document date, in the site’s timezone
data.line_count integer Number of lines
data.lines[].quantity number Quantity, always positive
data.lines[].item_name string|null The item’s name
data.lines[].transaction_id integer The ledger row this line wrote. 0 until finalized
data.warehouse_name string|null The warehouse’s name
data.created_at string UTC datetime

Errors

Status Code When
422 plugixa_inventory_invalid_choice movement_type is not one of the allowed values. data.allowed lists them.
422 plugixa_inventory_invalid_date movement_date is not a real date in the accepted form.
422 plugixa_inventory_missing_warehouse warehouse_id is missing.
422 plugixa_inventory_unknown_warehouse warehouse_id is not a live warehouse.
422 plugixa_inventory_unknown_recipient recipient_id is not a live recipient.
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 stock movement.

Plus the errors every endpoint can return.

Examples

curl -s -X POST "https://your-site.example/wp-json/plugixa-inventory/v1/stock-movements" \
  -u "admin:$WP_APP_PASSWORD" \
  -H "Content-Type: application/json" \
  -d '{"movement_type":"add_stock","warehouse_id":1,"movement_date":"2026-11-12 10:30","lines":[{"item_id":42,"quantity":120,"cost_per_unit":4.2,"notes":"Delivery note 4471"}]}'
<?php
$ch = curl_init('https://your-site.example/wp-json/plugixa-inventory/v1/stock-movements');
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([
        'movement_type' => 'add_stock',
        'warehouse_id'  => 1,
        'movement_date' => '2026-11-12 10:30',
        'lines'         => [
            [
                'item_id'       => 42,
                'quantity'      => 120,
                'cost_per_unit' => 4.2,
                'notes'         => 'Delivery note 4471',
            ],
        ],
    ]),
]);
$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/stock-movements', {
  method: 'POST',
  headers: { 'Authorization': auth, 'Content-Type': 'application/json' },
  body: JSON.stringify({
    movement_type: 'add_stock',
    warehouse_id: 1,
    movement_date: '2026-11-12 10:30',
    lines: [
      {
        item_id: 42,
        quantity: 120,
        cost_per_unit: 4.2,
        notes: 'Delivery note 4471',
      },
    ],
  }),
});
const { data } = await response.json();

Quick Links

Share