Purple ERP API Documentation

Machine-readable OpenAPI 3.0 specification: https://marketplace.moveworks.com/api/purple-suite/erp/openapi.json

The consolidated all-apps document at https://marketplace.moveworks.com/api/purple-suite/openapi.json can be narrowed to this app with ?apps=erp, or combined with other apps comma-separated (e.g. ?apps=erp,itsm).

Overview

--- **Acting as a user (`X-PS-Impersonate-User`).** Every endpoint accepts an optional `X-PS-Impersonate-User` request header whose value is the email of the instance user to act as. The effective user resolves in this order: the header if present, else the instance's configured default MCP user, else none. User-scoped paths additionally accept the literal `me` in place of an email, and Graph-style apps also serve `/me/…` twins of their `/users/{email}/…` paths that resolve the same way. This header is honored by all operations but is intentionally omitted from each operation's parameter list so it is not surfaced as a per-tool argument by MCP clients; see the `ImpersonateUser` entry under `components.parameters`.

Endpoints

GET /api/purple-suite/erp/purchase-orders

List ERP purchase orders (procurement commitments to vendors)

POs the company has raised against a vendor, with totalAmount, currency, lineItems, approver, expectedDelivery and status draft → pending_approval → approved → sent → partially_received → received (or cancelled). Vendor bills owed against these POs are invoices; employee out-of-pocket spend lives in the expense app. Supports server-side OData querying — _filter, _orderby, _select, _search, _top, _skip, _count (the spec names these $filter etc.; MCP clients see the _ form because $ is not a legal tool-input key).

Parameters

NameInTypeRequiredDescription
X-Instance-IDheaderstringyes
limitqueryintegernoLegacy page size (default 50). Prefer $top. Ignored when $top/$skip are used.
cursorquerystringnoLegacy keyset cursor — pass the previous response's nextCursor. Prefer $skip/$top.
$filterquerystringnoOData filter expression. Comparison operators: eq, ne, gt, ge, lt, le. Logical: and, or, not, with parentheses for grouping. String functions: contains(field,'x'), startswith(field,'x'), endswith(field,'x'). Membership: field in ('a','b'). Case-insensitive matching via tolower(field) / toupper(field). Nested fields use a slash, e.g. pto_balance/vacation_days. String literals use single quotes; dates are ISO-8601. Examples: "status eq 'active'"; "salary gt 50000 and department eq 'Engineering'"; "contains(tolower(name),'acme')"; "closeDate gt 2026-01-01".
$selectquerystringnoComma-separated list of fields to return, e.g. "id,firstName,email". Nested fields via slash ("pto_balance/vacation_days"). The id field is always included.
$orderbyquerystringnoSort clause(s), comma-separated, each "field [asc|desc]" (asc is the default). Example: "createdAt desc, lastName asc". Null values sort last.
$searchquerystringnoFree-text, case-insensitive substring match across the resource's searchable fields.
$topqueryintegernoMaximum number of items to return (page size).
$skipqueryintegernoNumber of matching items to skip before returning results (offset paging). Combine with $top.
$countquerybooleannoWhen true, include @odata.count (total matches after $filter/$search, before paging) in the response.

Responses

200
Paginated list

application/json

  • data array

    array of:

    PurchaseOrder

    • id string
    • vendor string
    • status string
    • totalAmount number
    • currency string
    • lineItems integer
    • approver string
    • expectedDelivery string
    • createdAt string
    • updatedAt string
  • nextCursor stringCursor for the next page, or null on the last page. With $top/$skip this is the next $skip value; otherwise a keyset cursor.
  • total integerTotal documents in the collection.
  • @odata.count integerPresent only when $count=true: total matches after $filter/$search.
  • @odata.truncated booleanPresent and true only when the collection exceeded the in-memory query cap and results may be incomplete.
400
Invalid OData query (e.g. malformed $filter)

POST /api/purple-suite/erp/purchase-orders

Create ERP purchase order (raise a new PO to a vendor)

Raises a new procurement commitment against a vendor, normally in draft or pending_approval. Use invoices for a bill you have already received, and the verify-match tool to reconcile a PO against its invoice and goods receipt.

Parameters

NameInTypeRequiredDescription
X-Instance-IDheaderstringyes

Request body

application/json — required

PurchaseOrder

  • id string
  • vendor string
  • status string
  • totalAmount number
  • currency string
  • lineItems integer
  • approver string
  • expectedDelivery string
  • createdAt string
  • updatedAt string

Responses

201
Created

application/json

PurchaseOrder

  • id string
  • vendor string
  • status string
  • totalAmount number
  • currency string
  • lineItems integer
  • approver string
  • expectedDelivery string
  • createdAt string
  • updatedAt string

GET /api/purple-suite/erp/purchase-orders/{id}

Get purchase order

Parameters

NameInTypeRequiredDescription
X-Instance-IDheaderstringyes
idpathstringyes

Responses

200
Found

application/json

PurchaseOrder

  • id string
  • vendor string
  • status string
  • totalAmount number
  • currency string
  • lineItems integer
  • approver string
  • expectedDelivery string
  • createdAt string
  • updatedAt string
404
Not found

DELETE /api/purple-suite/erp/purchase-orders/{id}

Delete purchase order

Parameters

NameInTypeRequiredDescription
X-Instance-IDheaderstringyes
idpathstringyes

Responses

200
Deleted

application/json

  • success boolean
404
Not found

PATCH /api/purple-suite/erp/purchase-orders/{id}

Update or transition an ERP purchase order

Partial update, and the way to move PO status through its lifecycle. State-machine rules are enforced: a cancelled PO cannot be modified at all, a fully 'received' PO cannot be cancelled, and only draft/pending_approval POs can be approved.

Parameters

NameInTypeRequiredDescription
X-Instance-IDheaderstringyes
idpathstringyes

Request body

Fields to update (partial)

application/json

PurchaseOrder

  • id string
  • vendor string
  • status string
  • totalAmount number
  • currency string
  • lineItems integer
  • approver string
  • expectedDelivery string
  • createdAt string
  • updatedAt string

Responses

200
Updated

application/json

PurchaseOrder

  • id string
  • vendor string
  • status string
  • totalAmount number
  • currency string
  • lineItems integer
  • approver string
  • expectedDelivery string
  • createdAt string
  • updatedAt string
404
Not found

POST /api/purple-suite/erp/purchase-orders/{id}/verify-match

3-way match verification

Parameters

NameInTypeRequiredDescription
X-Instance-IDheaderstringyes
idpathstringyes

Request body

application/json — required

  • invoice_id string required
  • receipt_confirmed boolean required

Responses

200
Match result

application/json

  • matched boolean
  • po_id string
  • invoice_id string
  • status string
404
Not found
422
Match validation failed

GET /api/purple-suite/erp/invoices

List ERP vendor invoices (accounts payable)

Bills the company owes suppliers, with vendor, amount, currency, dueDate, an optional poId link for 3-way match, and status draft → pending_payment → paid (or void / overdue). These are supplier bills — employee expense reports live in the expense app and customer billing is not modelled here. Supports server-side OData querying — _filter, _orderby, _select, _search, _top, _skip, _count (the spec names these $filter etc.; MCP clients see the _ form because $ is not a legal tool-input key).

Parameters

NameInTypeRequiredDescription
X-Instance-IDheaderstringyes
limitqueryintegernoLegacy page size (default 50). Prefer $top. Ignored when $top/$skip are used.
cursorquerystringnoLegacy keyset cursor — pass the previous response's nextCursor. Prefer $skip/$top.
$filterquerystringnoOData filter expression. Comparison operators: eq, ne, gt, ge, lt, le. Logical: and, or, not, with parentheses for grouping. String functions: contains(field,'x'), startswith(field,'x'), endswith(field,'x'). Membership: field in ('a','b'). Case-insensitive matching via tolower(field) / toupper(field). Nested fields use a slash, e.g. pto_balance/vacation_days. String literals use single quotes; dates are ISO-8601. Examples: "status eq 'active'"; "salary gt 50000 and department eq 'Engineering'"; "contains(tolower(name),'acme')"; "closeDate gt 2026-01-01".
$selectquerystringnoComma-separated list of fields to return, e.g. "id,firstName,email". Nested fields via slash ("pto_balance/vacation_days"). The id field is always included.
$orderbyquerystringnoSort clause(s), comma-separated, each "field [asc|desc]" (asc is the default). Example: "createdAt desc, lastName asc". Null values sort last.
$searchquerystringnoFree-text, case-insensitive substring match across the resource's searchable fields.
$topqueryintegernoMaximum number of items to return (page size).
$skipqueryintegernoNumber of matching items to skip before returning results (offset paging). Combine with $top.
$countquerybooleannoWhen true, include @odata.count (total matches after $filter/$search, before paging) in the response.

Responses

200
Paginated list

application/json

  • data array

    array of:

    Invoice

    • id string
    • vendor string
    • status string
    • amount number
    • currency string
    • dueDate string
    • poId stringPurchase order this invoice is linked to (used for 3-way match)
    • notes stringFree-text notes; the only field writable on a voided invoice
    • createdAt string
    • updatedAt string
  • nextCursor stringCursor for the next page, or null on the last page. With $top/$skip this is the next $skip value; otherwise a keyset cursor.
  • total integerTotal documents in the collection.
  • @odata.count integerPresent only when $count=true: total matches after $filter/$search.
  • @odata.truncated booleanPresent and true only when the collection exceeded the in-memory query cap and results may be incomplete.
400
Invalid OData query (e.g. malformed $filter)

POST /api/purple-suite/erp/invoices

Create ERP vendor invoice (record a bill in accounts payable)

Records a bill received from a vendor. Set poId to link it to the originating purchase order so the PO's verify-match tool can reconcile PO, invoice and receipt.

Parameters

NameInTypeRequiredDescription
X-Instance-IDheaderstringyes

Request body

application/json — required

Invoice

  • id string
  • vendor string
  • status string
  • amount number
  • currency string
  • dueDate string
  • poId stringPurchase order this invoice is linked to (used for 3-way match)
  • notes stringFree-text notes; the only field writable on a voided invoice
  • createdAt string
  • updatedAt string

Responses

201
Created

application/json

Invoice

  • id string
  • vendor string
  • status string
  • amount number
  • currency string
  • dueDate string
  • poId stringPurchase order this invoice is linked to (used for 3-way match)
  • notes stringFree-text notes; the only field writable on a voided invoice
  • createdAt string
  • updatedAt string

GET /api/purple-suite/erp/invoices/{id}

Get invoice

Parameters

NameInTypeRequiredDescription
X-Instance-IDheaderstringyes
idpathstringyes

Responses

200
Found

application/json

Invoice

  • id string
  • vendor string
  • status string
  • amount number
  • currency string
  • dueDate string
  • poId stringPurchase order this invoice is linked to (used for 3-way match)
  • notes stringFree-text notes; the only field writable on a voided invoice
  • createdAt string
  • updatedAt string
404
Not found

DELETE /api/purple-suite/erp/invoices/{id}

Delete invoice

Parameters

NameInTypeRequiredDescription
X-Instance-IDheaderstringyes
idpathstringyes

Responses

200
Deleted

application/json

  • success boolean
404
Not found

PATCH /api/purple-suite/erp/invoices/{id}

Update or transition an ERP vendor invoice

Partial update, and the way to move invoice status (e.g. pending_payment → paid). State-machine rules are enforced: a paid invoice cannot be voided (issue a credit memo or a reversal journal entry instead), a voided invoice cannot be marked paid, and a voided invoice is read-only apart from notes.

Parameters

NameInTypeRequiredDescription
X-Instance-IDheaderstringyes
idpathstringyes

Request body

Fields to update (partial)

application/json

Invoice

  • id string
  • vendor string
  • status string
  • amount number
  • currency string
  • dueDate string
  • poId stringPurchase order this invoice is linked to (used for 3-way match)
  • notes stringFree-text notes; the only field writable on a voided invoice
  • createdAt string
  • updatedAt string

Responses

200
Updated

application/json

Invoice

  • id string
  • vendor string
  • status string
  • amount number
  • currency string
  • dueDate string
  • poId stringPurchase order this invoice is linked to (used for 3-way match)
  • notes stringFree-text notes; the only field writable on a voided invoice
  • createdAt string
  • updatedAt string
404
Not found

GET /api/purple-suite/erp/inventory

List ERP inventory items (stocked goods by SKU)

On-hand stock records — itemName, sku, quantity, reorderPoint, unitCost and warehouseLocation. Use it for stock-on-hand and reorder questions; capitalised equipment is tracked in assets, buying more stock goes through purchase-orders, and live device telemetry lives in the dex app. Supports server-side OData querying — _filter, _orderby, _select, _search, _top, _skip, _count (the spec names these $filter etc.; MCP clients see the _ form because $ is not a legal tool-input key).

Parameters

NameInTypeRequiredDescription
X-Instance-IDheaderstringyes
limitqueryintegernoLegacy page size (default 50). Prefer $top. Ignored when $top/$skip are used.
cursorquerystringnoLegacy keyset cursor — pass the previous response's nextCursor. Prefer $skip/$top.
$filterquerystringnoOData filter expression. Comparison operators: eq, ne, gt, ge, lt, le. Logical: and, or, not, with parentheses for grouping. String functions: contains(field,'x'), startswith(field,'x'), endswith(field,'x'). Membership: field in ('a','b'). Case-insensitive matching via tolower(field) / toupper(field). Nested fields use a slash, e.g. pto_balance/vacation_days. String literals use single quotes; dates are ISO-8601. Examples: "status eq 'active'"; "salary gt 50000 and department eq 'Engineering'"; "contains(tolower(name),'acme')"; "closeDate gt 2026-01-01".
$selectquerystringnoComma-separated list of fields to return, e.g. "id,firstName,email". Nested fields via slash ("pto_balance/vacation_days"). The id field is always included.
$orderbyquerystringnoSort clause(s), comma-separated, each "field [asc|desc]" (asc is the default). Example: "createdAt desc, lastName asc". Null values sort last.
$searchquerystringnoFree-text, case-insensitive substring match across the resource's searchable fields.
$topqueryintegernoMaximum number of items to return (page size).
$skipqueryintegernoNumber of matching items to skip before returning results (offset paging). Combine with $top.
$countquerybooleannoWhen true, include @odata.count (total matches after $filter/$search, before paging) in the response.

Responses

200
Paginated list

application/json

  • data array

    array of:

    InventoryItem

    • id string
    • itemName string
    • sku string
    • quantity integer
    • reorderPoint integer
    • unitCost number
    • warehouseLocation string
    • createdAt string
    • updatedAt string
  • nextCursor stringCursor for the next page, or null on the last page. With $top/$skip this is the next $skip value; otherwise a keyset cursor.
  • total integerTotal documents in the collection.
  • @odata.count integerPresent only when $count=true: total matches after $filter/$search.
  • @odata.truncated booleanPresent and true only when the collection exceeded the in-memory query cap and results may be incomplete.
400
Invalid OData query (e.g. malformed $filter)

POST /api/purple-suite/erp/inventory

Create ERP inventory item (stock a new SKU)

Adds a stocked SKU with its opening quantity, reorder point, unit cost and warehouse location. For a capitalised piece of equipment create an asset instead.

Parameters

NameInTypeRequiredDescription
X-Instance-IDheaderstringyes

Request body

application/json — required

InventoryItem

  • id string
  • itemName string
  • sku string
  • quantity integer
  • reorderPoint integer
  • unitCost number
  • warehouseLocation string
  • createdAt string
  • updatedAt string

Responses

201
Created

application/json

InventoryItem

  • id string
  • itemName string
  • sku string
  • quantity integer
  • reorderPoint integer
  • unitCost number
  • warehouseLocation string
  • createdAt string
  • updatedAt string

GET /api/purple-suite/erp/inventory/{id}

Get inventory item

Parameters

NameInTypeRequiredDescription
X-Instance-IDheaderstringyes
idpathstringyes

Responses

200
Found

application/json

InventoryItem

  • id string
  • itemName string
  • sku string
  • quantity integer
  • reorderPoint integer
  • unitCost number
  • warehouseLocation string
  • createdAt string
  • updatedAt string
404
Not found

DELETE /api/purple-suite/erp/inventory/{id}

Delete inventory item

Parameters

NameInTypeRequiredDescription
X-Instance-IDheaderstringyes
idpathstringyes

Responses

200
Deleted

application/json

  • success boolean
404
Not found

PATCH /api/purple-suite/erp/inventory/{id}

Update inventory item

Parameters

NameInTypeRequiredDescription
X-Instance-IDheaderstringyes
idpathstringyes

Request body

Fields to update (partial)

application/json

InventoryItem

  • id string
  • itemName string
  • sku string
  • quantity integer
  • reorderPoint integer
  • unitCost number
  • warehouseLocation string
  • createdAt string
  • updatedAt string

Responses

200
Updated

application/json

InventoryItem

  • id string
  • itemName string
  • sku string
  • quantity integer
  • reorderPoint integer
  • unitCost number
  • warehouseLocation string
  • createdAt string
  • updatedAt string
404
Not found

GET /api/purple-suite/erp/journal-entries

List ERP general-ledger journal entries

Double-entry accounting records — type (debit/credit/adjustment/accrual/reversal), debitAccount, creditAccount, amount, accounting period and status draft → posted → reversed, plus reversalOf for entries created by a reversal. This is the GL; vendor bills are invoices and procurement commitments are purchase-orders. Supports server-side OData querying — _filter, _orderby, _select, _search, _top, _skip, _count (the spec names these $filter etc.; MCP clients see the _ form because $ is not a legal tool-input key).

Parameters

NameInTypeRequiredDescription
X-Instance-IDheaderstringyes
limitqueryintegernoLegacy page size (default 50). Prefer $top. Ignored when $top/$skip are used.
cursorquerystringnoLegacy keyset cursor — pass the previous response's nextCursor. Prefer $skip/$top.
$filterquerystringnoOData filter expression. Comparison operators: eq, ne, gt, ge, lt, le. Logical: and, or, not, with parentheses for grouping. String functions: contains(field,'x'), startswith(field,'x'), endswith(field,'x'). Membership: field in ('a','b'). Case-insensitive matching via tolower(field) / toupper(field). Nested fields use a slash, e.g. pto_balance/vacation_days. String literals use single quotes; dates are ISO-8601. Examples: "status eq 'active'"; "salary gt 50000 and department eq 'Engineering'"; "contains(tolower(name),'acme')"; "closeDate gt 2026-01-01".
$selectquerystringnoComma-separated list of fields to return, e.g. "id,firstName,email". Nested fields via slash ("pto_balance/vacation_days"). The id field is always included.
$orderbyquerystringnoSort clause(s), comma-separated, each "field [asc|desc]" (asc is the default). Example: "createdAt desc, lastName asc". Null values sort last.
$searchquerystringnoFree-text, case-insensitive substring match across the resource's searchable fields.
$topqueryintegernoMaximum number of items to return (page size).
$skipqueryintegernoNumber of matching items to skip before returning results (offset paging). Combine with $top.
$countquerybooleannoWhen true, include @odata.count (total matches after $filter/$search, before paging) in the response.

Responses

200
Paginated list

application/json

  • data array

    array of:

    JournalEntry

    • id string
    • type string
    • debitAccount string
    • creditAccount string
    • amount number
    • description string
    • status string
    • period string
    • postedAt stringISO timestamp when the entry was posted; set automatically on posted and reversal entries
    • reversalOf stringID of the original entry this reversal was created from
    • createdAt string
    • updatedAt string
  • nextCursor stringCursor for the next page, or null on the last page. With $top/$skip this is the next $skip value; otherwise a keyset cursor.
  • total integerTotal documents in the collection.
  • @odata.count integerPresent only when $count=true: total matches after $filter/$search.
  • @odata.truncated booleanPresent and true only when the collection exceeded the in-memory query cap and results may be incomplete.
400
Invalid OData query (e.g. malformed $filter)

POST /api/purple-suite/erp/journal-entries

Create ERP journal entry (book a GL debit/credit)

Books a new general-ledger entry for a period, normally as a draft that is later posted. To undo an already-posted entry use the reverse tool rather than editing or deleting the original.

Parameters

NameInTypeRequiredDescription
X-Instance-IDheaderstringyes

Request body

application/json — required

JournalEntry

  • id string
  • type string
  • debitAccount string
  • creditAccount string
  • amount number
  • description string
  • status string
  • period string
  • postedAt stringISO timestamp when the entry was posted; set automatically on posted and reversal entries
  • reversalOf stringID of the original entry this reversal was created from
  • createdAt string
  • updatedAt string

Responses

201
Created

application/json

JournalEntry

  • id string
  • type string
  • debitAccount string
  • creditAccount string
  • amount number
  • description string
  • status string
  • period string
  • postedAt stringISO timestamp when the entry was posted; set automatically on posted and reversal entries
  • reversalOf stringID of the original entry this reversal was created from
  • createdAt string
  • updatedAt string

GET /api/purple-suite/erp/journal-entries/{id}

Get journal entry

Parameters

NameInTypeRequiredDescription
X-Instance-IDheaderstringyes
idpathstringyes

Responses

200
Found

application/json

JournalEntry

  • id string
  • type string
  • debitAccount string
  • creditAccount string
  • amount number
  • description string
  • status string
  • period string
  • postedAt stringISO timestamp when the entry was posted; set automatically on posted and reversal entries
  • reversalOf stringID of the original entry this reversal was created from
  • createdAt string
  • updatedAt string
404
Not found

DELETE /api/purple-suite/erp/journal-entries/{id}

Delete journal entry

Parameters

NameInTypeRequiredDescription
X-Instance-IDheaderstringyes
idpathstringyes

Responses

200
Deleted

application/json

  • success boolean
404
Not found

PATCH /api/purple-suite/erp/journal-entries/{id}

Update or post an ERP journal entry

Partial update, most commonly setting status to 'posted'. State-machine rules are enforced: reversed entries are read-only, and on a posted entry the financial fields (amount, debitAccount, creditAccount) cannot be changed — create a reversal instead.

Parameters

NameInTypeRequiredDescription
X-Instance-IDheaderstringyes
idpathstringyes

Request body

Fields to update (partial)

application/json

JournalEntry

  • id string
  • type string
  • debitAccount string
  • creditAccount string
  • amount number
  • description string
  • status string
  • period string
  • postedAt stringISO timestamp when the entry was posted; set automatically on posted and reversal entries
  • reversalOf stringID of the original entry this reversal was created from
  • createdAt string
  • updatedAt string

Responses

200
Updated

application/json

JournalEntry

  • id string
  • type string
  • debitAccount string
  • creditAccount string
  • amount number
  • description string
  • status string
  • period string
  • postedAt stringISO timestamp when the entry was posted; set automatically on posted and reversal entries
  • reversalOf stringID of the original entry this reversal was created from
  • createdAt string
  • updatedAt string
404
Not found

POST /api/purple-suite/erp/journal-entries/{id}/reverse

Reverse a journal entry

Marks the entry as reversed and creates a new posted reversal entry with debit/credit swapped. Only posted entries can be reversed.

Parameters

NameInTypeRequiredDescription
X-Instance-IDheaderstringyes
idpathstringyes

Responses

201
Reversal entry created

application/json

JournalEntry

  • id string
  • type string
  • debitAccount string
  • creditAccount string
  • amount number
  • description string
  • status string
  • period string
  • postedAt stringISO timestamp when the entry was posted; set automatically on posted and reversal entries
  • reversalOf stringID of the original entry this reversal was created from
  • createdAt string
  • updatedAt string
404
Not found
422
Entry cannot be reversed in its current state

GET /api/purple-suite/erp/assets

List ERP fixed assets (the finance asset register)

Capitalised assets the company owns — IT Equipment, Furniture, Vehicle, Machinery, Building, Software License — with purchaseValue, currentValue, purchasedAt, location and status active/maintenance/retired/disposed. This is the finance-of-record register; live endpoint health for IT devices is in the dex app and consumable stock is in inventory. Supports server-side OData querying — _filter, _orderby, _select, _search, _top, _skip, _count (the spec names these $filter etc.; MCP clients see the _ form because $ is not a legal tool-input key).

Parameters

NameInTypeRequiredDescription
X-Instance-IDheaderstringyes
limitqueryintegernoLegacy page size (default 50). Prefer $top. Ignored when $top/$skip are used.
cursorquerystringnoLegacy keyset cursor — pass the previous response's nextCursor. Prefer $skip/$top.
$filterquerystringnoOData filter expression. Comparison operators: eq, ne, gt, ge, lt, le. Logical: and, or, not, with parentheses for grouping. String functions: contains(field,'x'), startswith(field,'x'), endswith(field,'x'). Membership: field in ('a','b'). Case-insensitive matching via tolower(field) / toupper(field). Nested fields use a slash, e.g. pto_balance/vacation_days. String literals use single quotes; dates are ISO-8601. Examples: "status eq 'active'"; "salary gt 50000 and department eq 'Engineering'"; "contains(tolower(name),'acme')"; "closeDate gt 2026-01-01".
$selectquerystringnoComma-separated list of fields to return, e.g. "id,firstName,email". Nested fields via slash ("pto_balance/vacation_days"). The id field is always included.
$orderbyquerystringnoSort clause(s), comma-separated, each "field [asc|desc]" (asc is the default). Example: "createdAt desc, lastName asc". Null values sort last.
$searchquerystringnoFree-text, case-insensitive substring match across the resource's searchable fields.
$topqueryintegernoMaximum number of items to return (page size).
$skipqueryintegernoNumber of matching items to skip before returning results (offset paging). Combine with $top.
$countquerybooleannoWhen true, include @odata.count (total matches after $filter/$search, before paging) in the response.

Responses

200
Paginated list

application/json

  • data array

    array of:

    Asset

    • id string
    • name string
    • type string
    • status string
    • purchaseValue number
    • currentValue number
    • purchasedAt stringDate the asset was originally purchased
    • location string
    • createdAt string
    • updatedAt string
  • nextCursor stringCursor for the next page, or null on the last page. With $top/$skip this is the next $skip value; otherwise a keyset cursor.
  • total integerTotal documents in the collection.
  • @odata.count integerPresent only when $count=true: total matches after $filter/$search.
  • @odata.truncated booleanPresent and true only when the collection exceeded the in-memory query cap and results may be incomplete.
400
Invalid OData query (e.g. malformed $filter)

POST /api/purple-suite/erp/assets

Create ERP fixed asset record

Registers a newly acquired capital asset with its type, purchase value and location. Consumable or resold stock belongs in inventory rather than here.

Parameters

NameInTypeRequiredDescription
X-Instance-IDheaderstringyes

Request body

application/json — required

Asset

  • id string
  • name string
  • type string
  • status string
  • purchaseValue number
  • currentValue number
  • purchasedAt stringDate the asset was originally purchased
  • location string
  • createdAt string
  • updatedAt string

Responses

201
Created

application/json

Asset

  • id string
  • name string
  • type string
  • status string
  • purchaseValue number
  • currentValue number
  • purchasedAt stringDate the asset was originally purchased
  • location string
  • createdAt string
  • updatedAt string

GET /api/purple-suite/erp/assets/{id}

Get asset

Parameters

NameInTypeRequiredDescription
X-Instance-IDheaderstringyes
idpathstringyes

Responses

200
Found

application/json

Asset

  • id string
  • name string
  • type string
  • status string
  • purchaseValue number
  • currentValue number
  • purchasedAt stringDate the asset was originally purchased
  • location string
  • createdAt string
  • updatedAt string
404
Not found

DELETE /api/purple-suite/erp/assets/{id}

Delete asset

Parameters

NameInTypeRequiredDescription
X-Instance-IDheaderstringyes
idpathstringyes

Responses

200
Deleted

application/json

  • success boolean
404
Not found

PATCH /api/purple-suite/erp/assets/{id}

Update asset

Parameters

NameInTypeRequiredDescription
X-Instance-IDheaderstringyes
idpathstringyes

Request body

Fields to update (partial)

application/json

Asset

  • id string
  • name string
  • type string
  • status string
  • purchaseValue number
  • currentValue number
  • purchasedAt stringDate the asset was originally purchased
  • location string
  • createdAt string
  • updatedAt string

Responses

200
Updated

application/json

Asset

  • id string
  • name string
  • type string
  • status string
  • purchaseValue number
  • currentValue number
  • purchasedAt stringDate the asset was originally purchased
  • location string
  • createdAt string
  • updatedAt string
404
Not found

POST /api/purple-suite/erp/purchase-requests

Create purchase request (legacy)

Stub endpoint kept for backwards compatibility (legacyUrl: /createPurchaseRequest). Always returns a fixed PR-LEGACY id.

Parameters

NameInTypeRequiredDescription
X-Instance-IDheaderstringyes

Request body

Purchase request payload (ignored by stub)

application/json

object

Responses

200
Submitted

application/json

  • purchase_request object
    • id string
    • status string

GET /api/purple-suite/erp/purchase-requests/pending

List pending purchase requests (legacy)

Stub endpoint kept for backwards compatibility (legacyUrl: /getPendingPurchases). Always returns an empty array.

Parameters

NameInTypeRequiredDescription
X-Instance-IDheaderstringyes

Responses

200
Empty list stub

application/json

array of:

GET /api/purple-suite/erp/purchase-requests/history

List historical purchase requests (legacy)

Stub endpoint kept for backwards compatibility (legacyUrl: /getHistoricalPurchases). Public (no auth required). Always returns an empty array.

Responses

200
Empty list stub

application/json

array of:

GET /api/purple-suite/erp/approvals

List approvals (legacy)

Stub endpoint kept for backwards compatibility (legacyUrl: /getApprovals). Always returns an empty data array.

Parameters

NameInTypeRequiredDescription
X-Instance-IDheaderstringyes

Responses

200
Empty list stub

application/json

  • success boolean
  • data array

    array of:

POST /api/purple-suite/erp/approvals

Create approval (legacy)

Stub endpoint kept for backwards compatibility (legacyUrl: /createApproval). Always returns APV-LEGACY id.

Parameters

NameInTypeRequiredDescription
X-Instance-IDheaderstringyes

Request body

Approval payload (ignored by stub)

application/json

object

Responses

200
Created

application/json

  • success boolean
  • data object
    • id string

PATCH /api/purple-suite/erp/approvals/{approvalId}

Update approval (legacy)

Stub endpoint kept for backwards compatibility (legacyUrl: /updateApproval). Always returns an empty data object.

Parameters

NameInTypeRequiredDescription
X-Instance-IDheaderstringyes
approvalIdpathstringyesApproval ID

Request body

Approval update payload (ignored by stub)

application/json

object

Responses

200
Updated

application/json

  • success boolean
  • data object