The Request Management plugin's API
Under /api/v1/x/requests, 404 while the plugin is off; requests:read and requests:write. Guide:
requests.
| Endpoint | What |
|---|---|
GET products?orgId=&active= | Products (request.read), with fields (the entitlements), fulfilment, and how many catalog items and active sold products each has. |
POST products, PATCH products/<id>, DELETE products/<id> | { orgId, key, name, description, fields, fulfilment: manual or automatic, active } (request.settings on the organization). key is a slug unique in the organization and never changes (409 key_taken). An entitlement field is { key, label, type: number, choice or multi, options: [{ id, label }], min, max, required, hint }; hint is help text shown under the input on the request form (at most 300 characters; empty is left out). Deleting a product in use is 409 in_use. |
GET items?orgId=&active=&productId= | Catalog items, with their product. |
POST items, PATCH items/<id>, DELETE items/<id> | { productId, unitId, name, description, action: new or change, fields, portalVisible, active, position } (request.settings). fields are the form's other questions, { key, label, type: text, long_text or choice, options, required, hint }, whose keys can't be the product's entitlements'. The product and action stay. position is the sort order: lower first, then by name. Deleting an item something was requested from is 409 in_use. |
GET ?status=&accountId=&q=&orgId=&page=&pageSize= | Requests (status: open, the default; all; or statuses with commas). q is a REQ-12 or an account's name. Answers { requests, total }. |
GET count | { open, submitted }. |
POST | A new request for an account, as staff (request.order in each item's unit): { accountId, contactId, items: [{ catalogItemId, soldProductId, answers }] }. answers is keyed by field key: a number, an option id, a list of option ids, or text. A change item names one of the account's active sold products of its product (soldProductId); entitlements not answered come from it. With Customer Service Management and a contact, a case is opened in the first item's unit, with the subject REQ-12: <item> and the answers as its description. |
GET <id or REQ-12> | The request: status, account, contact, orderedBy, case (when you may see it), decisionNote, decidedBy, itemsDetail (each with answers, originalAnswers, edited, state, details and its soldProduct), history and may. |
PATCH <id>/items/<itemId> | { answers } while it is submitted (request.write): the fields to change, null to clear one. The history keeps before and after. |
POST <id>/approve, POST <id>/reject | { note } (required to reject), while it is submitted (request.approve; 403 own_request for the person who made it). Approving moves the items to fulfilling; the requester is told on the case. |
POST <id>/cancel | { note }, before fulfilment started, or to close a request that needs attention (the note is required then; after an approval the requester gets it on the case) (request.write). |
POST <id>/items/<itemId>/fulfilment | { state: fulfilling, done or failed, note, details } (request.write): the fulfilment callback, also used by Mark done and Mark failed. details is an object of strings, numbers and booleans, merged into what the item keeps. done is final (409 after it): a new item creates the sold product, a change item updates its entitlements and merges the details. Every item done: the request is fulfilled; a failed one makes it needs_attention. |
GET sold-products?accountId=&productId=&status=&orgId=, GET sold-products/<id> | Sold products (status: active, the default; ended; all); one with the requests that made and changed it. |
POST sold-products/<id>/end | { note }: the account no longer has it (request.write, token scope requests:write). |
Request statuses: submitted, approved, fulfilling, fulfilled, needs_attention, rejected, cancelled. Item
states: pending, fulfilling, done, failed, cancelled.
The portal
Public, for a signed-in contact (their cookie), 404 for a portal that is off:
| Endpoint | What |
|---|---|
GET public/<slug>/catalog?locale= | { signedIn, contact, account, items }: the organization's active portal items, each with its product's fields, its own fields and, for a change item, the account's sold products of that product (soldProducts, with their entitlements). |
POST public/<slug>/orders | { catalogItemId, soldProductId, answers }, from the portal's own page (403 origin_not_allowed otherwise): answers { ref, caseRef }. |
Events
Each carries request: { id, ref, orgId } and account; never case content.
| Event | Data |
|---|---|
requests.submitted | request (with url and portal), account: { id, name }, items: [{ id, catalogItem, product: { id, key }, action }] |
requests.approved | request, account, contact, items (as in item below) |
requests.rejected | request, account, note |
requests.item_approved | Below. Sent for each item whose product has automatic fulfilment. |
requests.fulfilled | request, account, items |
requests.sold_product_ended | soldProduct (id, product.key, details), account.id, note |
requests.item_approved:
{
"request": { "id": "…", "ref": "REQ-12", "orgId": "…" },
"account": { "id": "…", "name": "Acme AS", "domains": ["acme.example"] },
"item": {
"id": "…",
"catalogItem": { "id": "…", "name": "New subscription" },
"product": { "id": "…", "key": "subscription", "name": "Subscription" },
"action": "new",
"soldProduct": null,
"entitlements": { "seats": 10, "modules": ["reports"] },
"answers": { "seats": 10, "modules": ["reports"], "notes": "Before the 1st" }
},
"callback": { "url": "https://desk.example/api/v1/x/requests/<id>/items/<itemId>/fulfilment" }
}
For a change item, soldProduct is { id, entitlements, details } as they are now. The receiver calls callback.url
with a requests:write token of someone with request.write in the request's unit.
MCP tools
| Scope | Tools |
|---|---|
requests:read | list_request_catalog (products and active catalog items), list_requests, get_request (by REQ-12 or id), list_sold_products |
requests:write | order_request, edit_request_item, decide_request (approve or reject), report_request_fulfilment |