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