Learning contextDemo Retail Group LLC12 stores · 2 distribution centres · AED/SAR/USD · omnichannel replenishmentChange scenario details →
Skip to content

OSERP API Library ​

The OSERP API is a versioned REST API for the web app, mobile clients, integrations, BI, POS, and AI tools. Base URL:

text
https://api.example.com/api/v1

The running application sets the global prefix to /api/v1. Replace the host with your deployment URL. This library describes routes present in the repository; a route marked configured still requires the caller’s tenant, company, and permission scope.

1. Authenticate and scope every request ​

Login ​

bash
curl -X POST "$OSERP_API/auth/login" \
  -H 'Content-Type: application/json' \
  -H 'X-Tenant-Id: tenant_demo' \
  -d '{"email":"admin@example.com","password":"change-me"}'

The response returns an access token and refresh token. Send the access token on every guarded call:

http
Authorization: Bearer <access-token>
X-Tenant-Id: tenant_demo
X-Organization-Id: org_demo
X-Company-Id: company_uae

The API enforces tenant isolation. Never accept a company, branch, warehouse, or ledger ID from an untrusted client without checking that it belongs to the authenticated scope.

Token lifecycle ​

MethodEndpointUse
GET/auth/lookup?email=Find the tenant invitation/account before login
POST/auth/loginCreate access and refresh tokens
POST/auth/unlockRe-authenticate an idle-locked session
POST/auth/refreshRotate a refresh token
POST/auth/logoutRevoke the current session
POST/auth/change-passwordChange the authenticated password

2. Response contract ​

Successful calls normally return:

json
{"success":true,"data":{"id":"item_01","code":"CHAIR-001"},"message":""}

Validation or business errors return a readable failure. Treat non-2xx responses and success:false as failures; do not infer success from HTTP 200 alone.

json
{"success":false,"error":{"code":"VALIDATION_ERROR","message":"quantity must be greater than zero","details":[]}}

Lists commonly accept search, page, limit, sorting, and module-specific filters. Monetary values are decimal strings or JSON numbers interpreted by the server; never calculate money with binary floating point in an integration.

3. CRUD endpoint catalogue ​

Companies and organisation ​

CRUDEndpointSample
ListGET /companies?page=1&limit=50&search=Dubai
CreatePOST /companies{ "name":"Virtux UAE", "baseCurrency":"AED" }
UpdatePATCH /companies/:id{ "name":"Virtux UAE FZ-LLC" }
DeleteDELETE /companies/:idDeactivate only when policy permits
Current tenantGET /tenants/currentResolves caller scope
OrganisationsGET /organizationsList organisations in scope

Items, prices, stock and warehouses ​

CRUDEndpointSample
List itemsGET /items?search=chair&categoryId=cat_furniture
Read itemGET /items/:idReturns master and configured attributes
Create itemPOST /items{ "code":"CHAIR-001", "name":"Oak chair", "uom":"PCS", "trackBatch":false }
Update itemPATCH /items/:id{ "name":"Oak dining chair" }
Delete itemDELETE /items/:idUse only when no posted history exists
StockGET /items/:id/stock?warehouseId=wh_dubai
Price for customerGET /items/:id/price?customerId=bp_lulu&branchId=br_dubai
CategoriesGET/POST/PATCH/DELETE /items/categories[/:catId]Create and maintain item hierarchy
Price listsGET/POST/PATCH /items/price-lists[/:priceListId]Bulk prices: POST /items/price-lists/:priceListId/bulk
WarehousesGET/POST/PATCH/DELETE /warehouses[/:id]{ "code":"WH-DXB", "name":"Dubai DC" }
ScanGET /items/scan/:codeBarcode or item code lookup

Business partners (customers and suppliers) ​

CRUDEndpointSample
SearchGET /business-partners/ref/search?search=LuluFast picker lookup
ListGET /business-partnersFilter by role, group, active state
ReadGET /business-partners/:idFull master, addresses, contacts
CreatePOST /business-partners{ "code":"CUST-001", "name":"Lulu Hypermarket", "roles":["CUSTOMER"] }
UpdatePATCH /business-partners/:idChange safe master fields
DeleteDELETE /business-partners/:idBlocked when posted documents exist
AddressPOST/PATCH/DELETE /business-partners/:id/addresses[/:addrId]Bill-to and ship-to
ContactPOST/PATCH/DELETE /business-partners/:id/contacts[/:contactId]Buyer and finance contacts
Credit profilePOST /business-partners/:id/credit-profileLimit, terms, risk policy
Block/unblockPOST /business-partners/:id/block / unblockControlled credit action

Sales documents and the 14-stage lifecycle ​

Sales documents are exposed through the process-workspace controller. The same resource carries quotation, order, delivery, invoice, payment, return, credit-note, collection, and closure stages.

CRUD / actionEndpointSample
ListGET /process-workspaces?processType=SALESPipeline and stage filters
ReadGET /process-workspaces/:idHeader, lines, stage state
CreatePOST /process-workspacesSee complete example below
Update headerPATCH /process-workspaces/:id/headerDates, terms, warehouse, dimensions
Add linePOST /process-workspaces/:id/linesItem, quantity, price, tax, warehouse
Update linePATCH /process-workspaces/:id/lines/:lineIdCorrect an unposted line
Delete lineDELETE /process-workspaces/:id/lines/:lineIdDraft/unposted only
Preview submitPOST /process-workspaces/:id/submit-previewShows missing fields and gates
SubmitPOST /process-workspaces/:id/submitCommits the current stage
AdvancePOST /process-workspaces/:id/advanceMove to next configured stage
Advance previewPOST /process-workspaces/:id/advance-previewSafe dry-run before transition
ChainGET /process-workspaces/:id/chainAll related stages
JournalGET /process-workspaces/:id/journalPosted accounting impact
ReversePOST /process-workspaces/:id/reverseControlled reversal

Create a quotation/order draft:

bash
curl -X POST "$OSERP_API/process-workspaces" \
  -H "Authorization: Bearer $TOKEN" -H 'Content-Type: application/json' \
  -H 'X-Tenant-Id: tenant_demo' -H 'X-Company-Id: company_uae' \
  -d '{
    "processType":"SALES", "stage":"QUOTATION", "counterpartyId":"bp_lulu",
    "documentDate":"2026-09-15", "postingDate":"2026-09-15",
    "currencyCode":"AED", "warehouseId":"wh_dubai", "paymentTermsId":"net30",
    "lines":[{"itemId":"item_chair_001","description":"Oak chair","quantity":100,"uom":"PCS","unitPrice":125.00,"discountPct":5,"taxPct":5,"warehouseId":"wh_dubai"}]
  }'

Advance only after checking the preview:

bash
curl -X POST "$OSERP_API/process-workspaces/doc_123/advance-preview" -H "Authorization: Bearer $TOKEN"
curl -X POST "$OSERP_API/process-workspaces/doc_123/advance" -H "Authorization: Bearer $TOKEN" -H 'Content-Type: application/json' -d '{"note":"Customer PO accepted"}'

Orders, POS and ecommerce ​

ModuleCRUD / action endpoints
OrdersGET/POST /orders, GET /orders/:id, POST /orders/:id/advance, /delivery, /cancel, /attach, /assign
POS salesPOST /pos/checkout, GET /pos/sales, GET /pos/sales/:id, POST /pos/sales/:id/void
POS returnsPOST /pos/returns/preview, POST /pos/returns
POS customersGET/POST /pos/customers, GET /pos/customers/:id/credit, /history
Ecommerce catalogueGET/PATCH /ecommerce/products[/:id], GET/PATCH /ecommerce/categories[/:id]
Ecommerce storesGET/POST/PATCH/DELETE /ecommerce/stores[/:id]

Accounting, vouchers and reports ​

CRUD / queryEndpoint
GroupsGET/POST /accounting/groups, PATCH /accounting/groups/:id
LedgersGET/POST /accounting/ledgers, PATCH /accounting/ledgers/:id
VouchersGET/POST /vouchers, GET /vouchers/:id, POST /vouchers/:id/reverse
Trial balanceGET /accounting/trial-balance
P&L / balance sheetGET /accounting/profit-and-loss, GET /accounting/balance-sheet
General ledgerGET /accounting/general-ledger
StatementsGET /accounting/statement/:direction
ReconciliationGET/POST /accounting/reconcile/:direction/allocate, history and unallocate routes
Tax summaryGET /accounting/tax-summary

Users, roles, projects and HR ​

ModuleCRUD endpoints
UsersGET/POST /users, GET /users/:id, PATCH /users/:id, DELETE /users/:id, POST /users/invite
RolesGET/POST /roles, GET /roles/:id, PATCH /roles/:id, DELETE /roles/:id
ProjectsGET/POST /projects, GET /projects/:id, PATCH /projects/:id, DELETE /projects/:id
EmployeesGET /hr/employees, GET /hr/employees/:id, PUT /hr/employees, PUT /hr/employments
PayrollGET/POST /payroll/runs, GET /payroll/runs/:id, POST /payroll/runs/:id/calculate, /approve, /post

4. Integration safety ​

  • Send a unique Idempotency-Key on invoice, payment, voucher, checkout, and stock-moving writes. Retry the same key; never create a new key for a network timeout.
  • Store access and refresh tokens in a secret store, never browser local storage for server integrations.
  • Use permission scopes such as sales:read, sales:write, inventory:read, customers:write, and reports:read.
  • Use webhook HMAC verification for external callbacks; retain the raw request body before parsing.
  • Log request ID, tenant, company, endpoint, actor, latency, and result—but never passwords or bearer tokens.
  • Use advance-preview and submit-preview before a batch transition. A successful HTTP response does not mean a document posted if its stage state is still a draft.

5. Practical error guide ​

SymptomCheck
401Access token expired; call /auth/refresh
403User/API key lacks permission or stage access
404ID is outside tenant/company scope or does not exist
Missing stage fieldsRead submit-preview; fill Stage details such as customer PO, transporter, payment mode, or cheque number
Invoice not postingPeriod lock, numbering, approval, tax, FX rate, or posting mapping
Duplicate supplier/paymentReuse the same idempotency key and inspect the existing document

For the complete implementation-level inventory, use the controller source and the repository API strategy. For business meaning, pair this library with the sales field guide and OSERP Atlas.

6. Resource contract cards for connector authors ​

The following cards are the minimum contract a connector should implement for each resource. Names are illustrative and must be checked against the deployed OpenAPI document. The important discipline is consistent identity, scope, precision, versioning, and state transitions.

Business partner card ​

GET /business-partners accepts tenantId, companyId, type, updatedAfter, status, limit, and cursor. Return id, code, name, type, taxRegistration, countryCode, currencyCode, paymentTermsId, status, version, createdAt, updatedAt, and scope identifiers. A policy-safe 404 is correct when an ID exists in another tenant.

json
{
  "id": "bp_lulu_001",
  "code": "LULU-UAE",
  "name": "Demo Lulu Hypermarket LLC",
  "type": "CUSTOMER",
  "taxRegistration": "AE123456789",
  "countryCode": "AE",
  "currencyCode": "AED",
  "paymentTermsId": "net30",
  "status": "ACTIVE",
  "version": 4,
  "scope": {"tenantId":"tenant_demo","companyId":"company_uae"}
}

POST requires an Idempotency-Key; replaying the same body and key returns the original resource. PATCH accepts mutable commercial fields only and requires If-Match: 4 or an equivalent version. Tax registration, legal identity, and historical currency are immutable after first posting; create a versioned amendment instead.

Item and warehouse card ​

POST /inventory/items creates the catalogue identity. Item code, UoM, valuation method, tax class, batch or serial rule, and active status are explicit fields. PATCH cannot change valuation method when posted stock exists. GET /inventory/stock is a position query, not a transaction: it returns warehouse, bin, lot or serial, available, reserved, quarantine, and unit-cost quantities.

json
{
  "itemCode": "CHAIR-OAK-001",
  "description": "Oak chair",
  "baseUom": "PCS",
  "valuationMethod": "MOVING_AVERAGE",
  "batchManaged": false,
  "taxCode": "VAT5",
  "status": "ACTIVE"
}

Stock-moving writes must include source document, warehouse, quantity, UoM, reason, and idempotency key. Do not implement a generic DELETE /stock; use receipt, issue, transfer, return, or approved adjustment so the ledger remains auditable.

Sales document card ​

The sales document resource has a header and lines. The header carries company, branch, customer, document and posting dates, currency, exchange-rate source, price list, payment terms, tax profile, warehouse, project, and external reference. Each line carries item or service, description, quantity, UoM, unit price, discount, tax, warehouse, project, and dimensions.

json
{
  "documentType":"INVOICE",
  "customerId":"bp_lulu_001",
  "documentDate":"2026-09-17",
  "postingDate":"2026-09-17",
  "currencyCode":"AED",
  "lines":[{"itemId":"item_chair_001","quantity":10,"uom":"PCS","unitPrice":125.00,"discountPct":5,"taxCode":"VAT5"}]
}

The server recalculates totals and tax; clients must not submit a trusted grand total. A response should expose net, tax, gross, rounding adjustment, status, version, journal status, and correlation ID. POST /sales/:id/advance-preview must be safe to repeat and must not create a journal. POST /sales/:id/advance performs the state transition after validations pass.

Payment and reconciliation card ​

Payment writes require payer, bank or cash account, value date, currency, amount, external reference, allocation, and fee. Allocation is a separate child operation because a receipt can be split across invoices. A payment response returns unapplied amount and allocation version. An allocation against a closed or foreign-company invoice is blocked.

json
{
  "payerId":"bp_lulu_001",
  "bankAccountId":"bank_dubai_01",
  "valueDate":"2026-09-17",
  "currencyCode":"AED",
  "amount":1312.50,
  "externalReference":"GATEWAY-8842",
  "fee":5.00
}

Reconciliation endpoints should return matched, unmatched, partially matched, and disputed states. Unallocate is a controlled reversal that requires reason and permission; it is not a silent delete of the original match.

Journal and reversal card ​

POST /vouchers requires company, book, posting date, currency context, source document, description, and balanced lines. Each line has account role or account ID, debit or credit, amount, tax, dimensions, and source reference. Money uses decimal strings or a fixed-precision representation; never binary floating point.

json
{
  "bookId":"IFRS-AED",
  "postingDate":"2026-09-17",
  "sourceType":"MANUAL_ADJUSTMENT",
  "lines":[
    {"accountId":"510100","debit":"1000.00","credit":"0.00","costCentre":"CC-DXB"},
    {"accountId":"110010","debit":"0.00","credit":"1000.00","costCentre":"CC-DXB"}
  ]
}

The server verifies debit equals credit at book precision, account activity, period status, required dimensions, permission, and duplicate source reference. Reversal creates a linked opposite journal with reason and actor; it does not mutate the posted voucher.

7. A connector’s end-to-end acceptance script ​

  1. Authenticate and record token scope, tenant, company, and correlation ID.
  2. Read the metadata or schema endpoint and validate field names, enum values, precision, and required dimensions.
  3. Create or locate a business partner using an idempotency key; replay the request and prove one record exists.
  4. Create an item and confirm that the response includes stable ID, code, version, and scope.
  5. Create a draft sales document with two lines, then call preview and inspect calculated net, tax, gross, and mapping path.
  6. Attempt a duplicate external reference, a closed-period date, a missing dimension, and an out-of-scope ID; prove each refusal has no partial posting.
  7. Advance the document, read the resulting journal, and reconcile line totals at document and base currency precision.
  8. Post a payment with a bank reference, replay it, allocate it to the invoice, and verify unapplied amount is zero.
  9. Receive a webhook, verify HMAC over the raw body, store event ID, replay it, and prove the handler is idempotent.
  10. Export audit events and retain request, response, actor, scope, version, timestamp, and correlation ID for the evidence pack.

This script is the minimum baseline for an AI agent, marketplace connector, bank integration, or data migration tool. A green HTTP status alone is not acceptance: the connector must prove business state, accounting state, scope isolation, and safe retry behavior.

OSERP™ Atlas · Understand every field. Master every workflow.