Contents

REST API - Plugixa Inventory

Everything the admin screens do, they do through this API. There is no private back channel, which is why it is worth documenting: if the app can do it, so can you.

Namespace

/wp-json/plugixa-inventory/v1/

Entities

Each registered entity gets the same CRUD surface, named after the entity:

Entity Base
Item /items
Category /categories
Warehouse /warehouses
Recipient /recipients
Stock movement /stock-movements
Transaction (ledger) /transactions
Transfer PRO /transfers
Adjustment PRO /adjustments
Unit PRO /units
GET    /items            list, with search, filters, sorting and paging
POST   /items            create
GET    /items/{id}       read one
PUT    /items/{id}       update
DELETE /items/{id}       trash

An absent module has no routes. A free site answers rest_no_route for /transfers, because the module is not installed - not because a licence check refused it. The same is true of an app switched off in the App Manager.

Routes that answer a question

Not everything is a record. These are the ones that are not:

Route Answers
GET /bootstrap Everything the app needs to start: settings, apps, vocabulary
GET /dashboard The dashboard’s figures
GET /warehouse-overview One location’s figures
GET /items/low-stock What is at or below its reorder level
GET /lookup One item from a barcode, SKU or serial
GET /lookup/search Several items from part of a name or code
GET /stock-movements/types The document types this build offers
GET /meta/entities What entities exist, and their fields
GET /apps / POST /apps Read and change the App Manager
GET /settings / POST /settings Read and save settings
GET /notifications The bell, with /unread-count and /read-all
POST /notifications/preferences Per-person alert choices
GET /import-targets, /imports The importer’s mapping targets and runs
GET /export/{entity} A list as CSV
POST /stock/reconcile, GET /stock/health The stock check
POST /stock/seed-layers Open cost layers from the ledger
GET /reports/... PRO The reporting screens
GET /roles/vocabulary, /roles/enforcement PRO The permission model, and whether it is being enforced
GET /user-roles PRO WordPress roles and their inventory capabilities
GET /custom-fields/types PRO The twelve field types
GET /pwa/manifest PRO The installable app manifest

Authentication and permissions

Standard WordPress: a logged-in session with a nonce, or application passwords for a script.

Every route answers through one permission method, and that method is handed the record, not just the action. This is what lets the Pro Roles module answer whose records without a single controller changing, and it is why the shortcode needed no authorisation code of its own: the front end talks to this same API and inherits the same answers.

A refused request is a refusal, not a redirect, and a list you may not read is empty rather than partial.

Filters are read after the permission check. A visitor who may not read an entity cannot learn which fields it has by asking what it can be filtered by.

What is never writable

  • The ledger. There is no route to update or delete a transaction row, and a veto in the data layer refuses it even if code tried.
  • On hand. Stock is the result of finalised documents. It is not in the list of fields an item update may touch.
  • A finalised document. Post the opposite document instead.

These are not permissions you can grant. See The Stock Ledger.

Errors

Ordinary WordPress error shapes, with a code you can branch on: 422 for a validation problem naming the field, 409 for a conflict such as a duplicate SKU or a document that cannot be trashed - with the blocking reasons listed - and 403 for a refusal.

One deliberate exception: GET /lookup answers 200 with found: false for an unknown code, rather than 404. A scanning loop that had to tell an HTTP error apart from a miss would treat a network failure as an unknown item.

Extending it

plugixa_inventory_register_rest_routes fires with the namespace and the container, so your own routes can sit in the same namespace and reuse the same permission model. See Hooks.

Troubleshooting

Symptom Usual cause
rest_no_route The module is absent, or its app is switched off.
401 from a script Use an application password, or send a nonce.
403 on a record you can see in a list A Pro permission profile scopes edit or delete more narrowly than read.
A list is empty for one user and full for another Permission scoping. That is the feature.
409 on create A duplicate SKU or barcode. The message names the other record.
409 on delete Something depends on it. The blockers are in the response.
On hand will not update Correct. Post a stock movement.
A lookup miss returns 200 By design, so a miss cannot be confused with a failure.

What to do next

Quick Links