# Vertex Warehouse — API Vertex Warehouse is an asset / inventory system. Its vocabulary is **Assets · Reservations · Locations · Stock**. A record is an Asset identified by `asset_tag` (for example `VX-88213`). Base URL: `https://necogoode-systems.azurewebsites.net` Authentication: none (demo system, public). Content type: `application/json`. ## Identifiers this system emits | Identifier | Example | Notes | |---|---|---| | `asset_tag` | VX-88213 | the physical asset tag | | `employee_no` | E10488 | the warehouse's own employee number | > Vertex Warehouse holds **neither an email address nor a ContactId**. Joining an Asset to the other systems has to go through a person record mapping `employee_no` to an email. Any email or ContactId sent to this API is dropped and reported back in `droppedFields`. ## Endpoints ### `GET /api/warehouse/records` List every Asset, newest first. ```bash curl -s https://necogoode-systems.azurewebsites.net/api/warehouse/records ``` ```json { "ok": true, "count": 1, "records": [ { "asset_tag": "VX-88213", "createdAt": "2026-08-29T09:14:02.113Z", "eventCount": 2, "lastDelivery": { "httpStatus": 202, "receiptStatus": "accepted", "receiptReason": null } } ] } ``` ### `POST /api/warehouse/records` Create an Asset. **Emits `vertex.asset.registered`.** ```bash curl -s -X POST https://necogoode-systems.azurewebsites.net/api/warehouse/records \ -H 'content-type: application/json' \ -d '{ "asset_type": "Laptop", "model": "Vertex Pro 14", "employee_no": "E10488", "stock_location": "Chicago DC", "stock_status": "In stock", "quantity": 1 }' ``` ```json { "ok": true, "record": { "asset_tag": "VX-88213", ... }, "event": { "eventType": "vertex.asset.registered", "externalEventId": "warehouse-VX-88213-0001", "delivery": { "httpStatus": 202, "receiptStatus": "accepted", "receiptReason": null } } } ``` Optional body keys on every write: `occurredAt` (ISO — backdates the record and the event) and `emit: false` (suppress the webhook). A create missing a required field returns `400 { "ok": false, "error": "missing required field(s): ..." }`. Identifiers belonging to another system are dropped before the record is written and returned in `droppedFields`. #### Body fields | Field | Type | Required | Notes | |---|---|---|---| | `asset_type` | string (enum) | no | Asset type — one of: `Laptop`, `Docking station`, `Monitor`, `Handset`, `Headset` | | `model` | string | no | Model | | `employee_no` | string | yes | Employee no. | | `stock_location` | string (enum) | no | Stock location — one of: `Chicago DC`, `Reno DC`, `Rotterdam DC` | | `cost_centre` | string | no | Cost centre | | `stock_status` | string (enum) | no | Stock status — one of: `In stock`, `Reserved`, `Picked`, `Shipped`, `Retired` | | `quantity` | number | no | Quantity | | `reservation_ref` | string | no | Reservation ref | | `notes` | string | no | Notes | ### `GET /api/warehouse/records/{id}` Read one Asset. 404 if unknown. ### `PATCH /api/warehouse/records/{id}` Update an Asset. **Emits `vertex.asset.updated`** with a new `externalEventId` and the same `asset_tag`. The payload carries `changedFields`, an array of the field names supplied. ```bash curl -s -X PATCH https://necogoode-systems.azurewebsites.net/api/warehouse/records/VX-88213 \ -H 'content-type: application/json' -d '{"stock_location":"Reno DC","cost_centre":"CC-4120"}' ``` ### `POST /api/warehouse/records/{id}/reserve` Reserve the Asset out of a stock Location against an employee number. **Emits `vertex.reservation.created`.** ```bash curl -s -X POST https://necogoode-systems.azurewebsites.net/api/warehouse/records/VX-88213/reserve \ -H 'content-type: application/json' -d '{"location":"Chicago DC","employee_no":"E10488"}' ``` | Body field | Type | Required | Notes | |---|---|---|---| | `location` | string | yes | one of: `Chicago DC`, `Reno DC`, `Rotterdam DC` | | `employee_no` | string | no | | ### `GET /api/warehouse/records/{id}/events` Every event Vertex Warehouse has emitted for that record, oldest first, each with the SoloLift delivery outcome. ### `GET /api/warehouse/events?limit=200` Every event this system has emitted, newest first. ### `POST /api/warehouse/chaos` Emit a deliberately awkward event so anomaly detection can be exercised. `{ "mode": "out_of_order" | "duplicate" | "omit_field" | "unknown_type", "recordId": "VX-88213" }` | Mode | What it does | |---|---| | `out_of_order` | emits `vertex.asset.updated` stamped 36h **before** the record was created | | `duplicate` | replays the record's last event verbatim, reusing its `externalEventId` | | `omit_field` | emits an update whose payload is missing the normally-present `employee_no` | | `unknown_type` | emits `vertex.asset.levitated`, a type this system does not normally emit | ### `POST /api/warehouse/seed` Generate backdated history. `{ "count": 20, "from": "2026-06-20T00:00:00Z", "to": "2026-08-29T00:00:00Z", "includeAction": true }` Optional: `fieldRatios` (probability an optional field is populated, e.g. `{"CostCentre":0.35}`), `specialistRatio`, `template` (values forced onto every seeded record), `emit:false`. ### `GET /api/_health` `{ "ok": true, "build": "" }` ## Events emitted | Event type | When | Payload fields | |---|---|---| | `vertex.asset.registered` | a Asset is created | `asset_tag`, `asset_type`, `model`, `employee_no`, `stock_location`, `cost_centre`, `stock_status`, `quantity`, `reservation_ref`, `notes`, `createdAt` | | `vertex.asset.updated` | a Asset is edited or re-submitted | as above, plus `changedFields` | | `vertex.reservation.created` | reserve stock | as above, plus `reservation_ref`, `reserved_at`, `from_location`, `quantity` | | `vertex.asset.levitated` | chaos only — never emitted in normal operation | as above | Each emission POSTs to `{SOLOLIFT_BASE_URL}/api/v1/events/ingest` with `x-sololift-signature: sha256=` and the envelope `{ eventSourceId, externalEventId, eventType, subject, occurredAt, payload }`. `externalEventId` is `warehouse--<4-digit sequence>`.