API Reference
Arkan ERP provides a RESTful API for all platform operations, plus WebSocket support for real-time events.
Base URL
https://your-api-host/api/v1Authentication
All requests require a Bearer token in the Authorization header:
curl -H "Authorization: Bearer YOUR_TOKEN" \
-H "X-Company-Id: COMPANY_UUID" \
https://your-api-host/api/v1/projectsGet a Token
POST /api/v1/auth/login
Content-Type: application/json
{
"email": "user@example.com",
"password": "your-password"
}Response:
{
"accessToken": "eyJhbGciOiJIUzI1NiIs...",
"refreshToken": "eyJhbGciOiJIUzI1NiIs...",
"expiresIn": 3600
}Refresh a Token
POST /api/v1/auth/refresh
Content-Type: application/json
{
"refreshToken": "eyJhbGciOiJIUzI1NiIs..."
}Access tokens expire after 1 hour. Use the refresh token to obtain a new access token without re-authenticating.
Company Context
Set the X-Company-Id header to scope requests to a specific company. This header is required for all endpoints except /auth and /companies.
X-Company-Id: 550e8400-e29b-41d4-a716-446655440000See Multi-Company for details on company isolation.
Pagination
All list endpoints support cursor-based pagination:
| Parameter | Type | Default | Description |
|---|---|---|---|
limit | number | 25 | Items per page (max 100) |
cursor | string | — | Cursor from previous response |
sort | string | createdAt | Sort field |
order | string | desc | Sort direction (asc or desc) |
Response includes pagination metadata:
{
"data": [ ... ],
"meta": {
"total": 142,
"limit": 25,
"cursor": "eyJpZCI6IjEyMyJ9",
"hasMore": true
}
}Rate Limiting
API requests are rate-limited per tenant:
| Plan | Requests/minute | Burst |
|---|---|---|
| Free | 60 | 10 |
| Starter | 120 | 20 |
| Professional | 300 | 50 |
| Business | 600 | 100 |
| Enterprise | 1200 | 200 |
Rate limit headers are included in every response:
X-RateLimit-Limit: 300
X-RateLimit-Remaining: 297
X-RateLimit-Reset: 1713024060Accounting
Chart of Accounts
| Method | Path | Description |
|---|---|---|
| GET | /accounting/accounts | List chart of accounts |
| POST | /accounting/accounts | Create an account |
| GET | /accounting/accounts/:id | Get account details |
| PATCH | /accounting/accounts/:id | Update an account |
Journal Entries
| Method | Path | Description |
|---|---|---|
| POST | /accounting/journal-entries | Create a journal entry |
| GET | /accounting/journal-entries | List journal entries |
| GET | /accounting/journal-entries/:id | Get entry details |
| POST | /accounting/journal-entries/:id/post | Post a draft entry |
Invoices & Bills
| Method | Path | Description |
|---|---|---|
| GET | /accounting/invoices | List invoices |
| POST | /accounting/invoices | Create an invoice |
| POST | /accounting/invoices/:id/post | Post a draft invoice |
| POST | /accounting/invoices/:id/cancel | Cancel with credit note |
Payments
| Method | Path | Description |
|---|---|---|
| GET | /accounting/payments | List payments |
| POST | /accounting/payments | Record a payment |
| POST | /accounting/payments/:id/post | Post a draft payment |
| POST | /accounting/payments/:id/allocate | Allocate to invoices |
Batch Payment Export
| Method | Path | Description |
|---|---|---|
| GET | /accounting/batch-payment/exportable | List payments eligible for export |
| POST | /accounting/batch-payment/export/uaefts | Export as UAEFTS file (UAE bank transfer) |
| POST | /accounting/batch-payment/export/csv | Export as CSV file |
| POST | /accounting/batch-payment/export/wps | Export as WPS/SIF file (salary payments) |
| PUT | /accounting/batch-payment/bank-details/:partnerId | Save partner bank details |
| GET | /accounting/batch-payment/bank-details/:partnerId | Get partner bank details |
Invoice Margin
| Method | Path | Description |
|---|---|---|
| GET | /accounting/invoice-margin/:invoiceId | Get margin for a single invoice |
| GET | /accounting/invoice-margin/report | Margin report for a date range |
Financial Reports
| Method | Path | Description |
|---|---|---|
| GET | /accounting/reports/profit-loss | Profit & Loss statement |
| GET | /accounting/reports/balance-sheet | Balance Sheet |
| GET | /accounting/reports/cash-flow | Cash Flow statement |
| GET | /accounting/reports/aged-receivables | Aged receivables |
| GET | /accounting/reports/aged-payables | Aged payables |
| GET | /accounting/reports/revenue-by-client | Revenue by client |
| GET | /accounting/reports/revenue-by-project | Revenue by project |
| GET | /accounting/reports/budget-vs-actual | Budget vs actual |
| GET | /accounting/reports/tax | Tax report |
Bank Reconciliation
| Method | Path | Description |
|---|---|---|
| POST | /accounting/bank-reconciliation/statements | Import a bank statement |
| GET | /accounting/bank-reconciliation/statements | List bank statements |
| POST | /accounting/bank-reconciliation/match | Match statement line to entry |
| POST | /accounting/bank-reconciliation/write-off | Write off small difference |
Fixed Assets
| Method | Path | Description |
|---|---|---|
| POST | /accounting/assets | Create an asset |
| GET | /accounting/assets | List assets |
| POST | /accounting/assets/:id/depreciate | Run depreciation |
| POST | /accounting/assets/:id/dispose | Dispose an asset |
Sales
Orders
| Method | Path | Description |
|---|---|---|
| GET | /sales/orders | List sales orders |
| POST | /sales/orders | Create an order |
| GET | /sales/orders/:id | Get order details |
| PATCH | /sales/orders/:id | Update an order |
| POST | /sales/orders/:id/confirm | Confirm an order |
| POST | /sales/orders/:id/cancel | Cancel an order |
Quotes
| Method | Path | Description |
|---|---|---|
| GET | /sales/quotes | List quotes |
| POST | /sales/quotes | Create a quote |
| POST | /sales/quotes/:id/send | Send quote to client |
| POST | /sales/quotes/:id/accept | Accept a quote |
| POST | /sales/quotes/:id/convert-to-order | Convert to sales order |
Billing & Down Payments
| Method | Path | Description |
|---|---|---|
| POST | /sales/billing/invoice/:orderId | Create invoice from order |
| POST | /sales/billing/down-payment/:orderId | Create deposit invoice |
| POST | /sales/billing/credit-note/:invoiceId | Create credit note |
| GET | /sales/billing/summary/:orderId | Billing summary for order |
| POST | /sales/billing/cogs/:deliveryId | Create COGS entry |
Deliveries
| Method | Path | Description |
|---|---|---|
| POST | /sales/deliveries/from-order/:orderId | Create delivery from order |
| GET | /sales/deliveries | List deliveries |
| POST | /sales/deliveries/:id/confirm | Confirm delivery |
| POST | /sales/deliveries/:id/deliver | Mark as delivered |
| GET | /sales/deliveries/atp/:productId | Available-to-promise |
Returns
| Method | Path | Description |
|---|---|---|
| POST | /sales/returns | Create a return |
| POST | /sales/returns/:id/receive | Receive returned goods |
| POST | /sales/returns/:id/refund | Process refund |
Pricing & Discounts
| Method | Path | Description |
|---|---|---|
| GET | /sales/pricing/resolve | Resolve product price |
| POST | /sales/pricing/lists | Create price list |
| POST | /sales/discounts/evaluate | Evaluate applicable discounts |
| GET | /sales/discounts/validate-promo | Validate promo code |
Commissions
| Method | Path | Description |
|---|---|---|
| POST | /sales/commissions/rules | Create commission rule |
| GET | /sales/commissions/rules | List commission rules |
| GET | /sales/commissions/calculate | Calculate commissions for period |
| GET | /sales/commissions/summary | Commission summary per salesperson |
Suggestions (Upsell / Cross-sell)
| Method | Path | Description |
|---|---|---|
| GET | /sales/suggestions?product_ids=x,y | Get product suggestions |
Returns three types: frequently_bought_together, upsell, category_companions.
Warnings
| Method | Path | Description |
|---|---|---|
| GET | /sales/warnings?entity_type=client&entity_id=x | Get warnings for entity |
| GET | /sales/warnings/check-order?client_id=x&product_ids=a,b | Check all warnings for order |
| POST | /sales/warnings | Create manual warning |
| DELETE | /sales/warnings/:id | Remove a warning |
Incoterms
| Method | Path | Description |
|---|---|---|
| GET | /sales/incoterms | List all Incoterms 2020 codes |
Subscriptions
| Method | Path | Description |
|---|---|---|
| POST | /sales/subscriptions | Create subscription |
| POST | /sales/subscriptions/:id/activate | Activate |
| POST | /sales/subscriptions/:id/pause | Pause |
| POST | /sales/subscriptions/generate-invoices | Generate due invoices |
Inventory & Warehousing
Products
| Method | Path | Description |
|---|---|---|
| GET | /inventory/products | List products with stock levels |
| POST | /inventory/products | Create a product |
| GET | /inventory/products/:id | Get product details |
| GET | /inventory/products/:id/stock | Get stock by location |
Stock Operations
| Method | Path | Description |
|---|---|---|
| POST | /inventory/moves | Create a stock move |
| POST | /inventory/moves/transfer | Transfer between locations |
| POST | /inventory/adjustments | Create inventory adjustment |
| POST | /inventory/cycle-counts | Start a cycle count session |
| POST | /inventory/barcode/quick-move | Quick move via barcode |
Scrap Management
| Method | Path | Description |
|---|---|---|
| POST | /inventory/scrap | Create a scrap order |
| GET | /inventory/scrap | List scrap entries |
| GET | /inventory/scrap/reasons | Get available scrap reasons |
Putaway Strategies
| Method | Path | Description |
|---|---|---|
| POST | /inventory/putaway/rules | Create putaway rule |
| GET | /inventory/putaway/rules | List putaway rules |
| DELETE | /inventory/putaway/rules/:id | Delete a rule |
| GET | /inventory/putaway/resolve?warehouse_id=x&product_id=y | Resolve location for product |
Routing Rules
| Method | Path | Description |
|---|---|---|
| POST | /inventory/routing | Create warehouse route |
| GET | /inventory/routing | List routes |
| GET | /inventory/routing/:id | Get route details |
| PATCH | /inventory/routing/:id | Update route |
| DELETE | /inventory/routing/:id | Delete route |
| GET | /inventory/routing/resolve/:warehouseId/:type | Resolve route for operation |
Purchasing
| Method | Path | Description |
|---|---|---|
| POST | /inventory/purchase-orders | Create PO |
| GET | /inventory/purchase-orders | List POs |
| POST | /inventory/purchase-orders/:id/approve | Approve PO |
| POST | /inventory/purchase-orders/:id/confirm | Confirm PO |
| POST | /inventory/purchase-orders/:id/receive | Receive goods |
| POST | /inventory/rfqs | Create RFQ |
| GET | /inventory/rfqs/:id/compare | Compare vendor quotes |
| POST | /inventory/blanket-orders | Create blanket order |
| POST | /inventory/blanket-orders/:id/call-off | Create call-off PO |
Purchase Agreements (Tenders)
| Method | Path | Description |
|---|---|---|
| POST | /inventory/purchase-agreements | Create a tender |
| GET | /inventory/purchase-agreements | List tenders |
| POST | /inventory/purchase-agreements/:id/open | Open for bidding |
| POST | /inventory/purchase-agreements/:id/bids | Submit a bid |
| POST | /inventory/purchase-agreements/:id/evaluate | Start evaluation |
| POST | /inventory/purchase-agreements/:id/award | Award to vendor |
| GET | /inventory/purchase-agreements/:id/compare | Bid comparison table |
Vendor Rating
| Method | Path | Description |
|---|---|---|
| GET | /inventory/vendor-rating/ranking | Vendor ranking by score |
| GET | /inventory/vendor-rating/:vendorId | Vendor scorecard |
Valuation & Costing
| Method | Path | Description |
|---|---|---|
| GET | /inventory/valuation | Inventory valuation report |
| GET | /inventory/valuation/by-category | Valuation by category |
| GET | /inventory/standard-cost/variances | Cost variance report |
| POST | /inventory/landed-costs | Create landed cost |
Reports
| Method | Path | Description |
|---|---|---|
| GET | /inventory/reports/turnover | Inventory turnover |
| GET | /inventory/reports/abc | ABC classification |
| GET | /inventory/reports/aging | Inventory aging |
| GET | /inventory/reports/dead-stock | Dead stock analysis |
| GET | /inventory/reports/forecast | Demand forecast |
CRM
| Method | Path | Description |
|---|---|---|
| GET | /crm/leads | List leads |
| POST | /crm/leads | Create a lead |
| POST | /crm/leads/:id/convert | Convert lead to deal |
| GET | /crm/deals | List deals |
| PATCH | /crm/deals/:id | Update a deal |
| GET | /crm/clients | List clients |
| POST | /crm/clients | Create a client |
| GET | /crm/contacts | List contacts |
HR & Payroll
| Method | Path | Description |
|---|---|---|
| GET | /hr/employees | List employees |
| POST | /hr/employees | Create an employee |
| GET | /hr/payroll/runs | List payroll runs |
| POST | /hr/payroll/runs | Create a payroll run |
| POST | /hr/payroll/runs/:id/post | Post payroll to GL |
| GET | /hr/leave/requests | List leave requests |
| POST | /hr/leave/requests | Submit a leave request |
| GET | /hr/attendance | List attendance records |
Projects
| Method | Path | Description |
|---|---|---|
| GET | /projects | List projects |
| POST | /projects | Create a project |
| GET | /projects/:id | Get project details |
| GET | /projects/:id/work-items | List work items |
| POST | /projects/:id/work-items | Create a work item |
| GET | /projects/:id/sprints | List sprints |
| POST | /projects/:id/sprints | Create a sprint |
Odoo Data Import
Full migration toolkit for importing data from Odoo instances. See Import Tool for detailed documentation.
Sessions
| Method | Path | Description |
|---|---|---|
| POST | /import/sessions | Create import session |
| GET | /import/sessions | List sessions |
| GET | /import/sessions/:id | Get session details |
| GET | /import/sessions/:id/errors | Get import errors |
| GET | /import/sessions/:id/mappings | Get Odoo→Arkan ID mappings |
| POST | /import/sessions/:id/complete | Mark session complete |
CSV Import
| Method | Path | Description |
|---|---|---|
| POST | /import/analyze | Analyze CSV (detect model, preview data) |
| POST | /import/validate | Validate CSV against model rules |
| POST | /import/sessions/:id/import/accounts | Import chart of accounts |
| POST | /import/sessions/:id/import/journals | Import journals |
| POST | /import/sessions/:id/import/taxes | Import taxes |
| POST | /import/sessions/:id/import/categories | Import product categories |
| POST | /import/sessions/:id/import/uom | Import units of measure |
| POST | /import/sessions/:id/import/partners | Import clients & vendors |
| POST | /import/sessions/:id/import/products | Import products |
| POST | /import/sessions/:id/import/warehouses | Import warehouses |
| POST | /import/sessions/:id/import/locations | Import locations |
| POST | /import/sessions/:id/import/opening-stock | Import opening stock |
| POST | /import/sessions/:id/import/journal-entries | Import journal entries |
| POST | /import/sessions/:id/import/payments | Import payments |
| POST | /import/sessions/:id/import/sales-orders | Import sales orders |
| POST | /import/sessions/:id/import/purchase-orders | Import purchase orders |
| POST | /import/sessions/:id/import/opening-balance | Generate opening balance entry |
Odoo Live Connector
| Method | Path | Description |
|---|---|---|
| POST | /import/odoo/connect | Test connection to Odoo |
| POST | /import/odoo/summary | Get record counts from Odoo |
| POST | /import/odoo/fields | List model fields |
| POST | /import/odoo/extract | Extract records as JSON + CSV |
| POST | /import/odoo/extract-and-import | Extract and import in one step |
Post-Import Validation
| Method | Path | Description |
|---|---|---|
| POST | /import/sessions/:id/validate | Run validation (trial balance, record counts, FK integrity) |
Customer Portal
Token-based self-service portal for customers. Tokens are generated by admin users and shared with clients.
Admin Endpoints (JWT required)
| Method | Path | Description |
|---|---|---|
| POST | /customer-portal/tokens | Generate portal token for client |
| GET | /customer-portal/tokens | List active tokens |
| DELETE | /customer-portal/tokens/:id | Revoke a token |
Public Endpoints (token-based)
| Method | Path | Description |
|---|---|---|
| GET | /customer-portal/view/:token/dashboard | Customer dashboard |
| GET | /customer-portal/view/:token/quotes | List quotes |
| POST | /customer-portal/view/:token/quotes/:id/accept | Accept a quote |
| POST | /customer-portal/view/:token/quotes/:id/decline | Decline a quote |
| GET | /customer-portal/view/:token/orders | List orders |
| GET | /customer-portal/view/:token/orders/:id | Order details with deliveries |
| GET | /customer-portal/view/:token/invoices | List invoices |
| GET | /customer-portal/view/:token/payments | Payment history |
| GET | /customer-portal/view/:token/deliveries | Delivery tracking |
Vendor Portal
Token-based self-service portal for vendors (suppliers). See Vendor Portal for details.
Admin Endpoints (JWT required)
| Method | Path | Description |
|---|---|---|
| POST | /vendor-portal/tokens | Generate token for vendor |
| GET | /vendor-portal/tokens | List active tokens |
| DELETE | /vendor-portal/tokens/:id | Revoke a token |
Public Endpoints (token-based)
| Method | Path | Description |
|---|---|---|
| GET | /vendor-portal/view/:token/dashboard | Vendor dashboard |
| GET | /vendor-portal/view/:token/purchase-orders | List POs |
| GET | /vendor-portal/view/:token/purchase-orders/:id | PO detail |
| POST | /vendor-portal/view/:token/purchase-orders/:id/acknowledge | Acknowledge PO |
| POST | /vendor-portal/view/:token/purchase-orders/:id/shipping | Update shipping info |
| POST | /vendor-portal/view/:token/invoices | Submit vendor invoice |
| GET | /vendor-portal/view/:token/invoices | View submitted invoices |
| GET | /vendor-portal/view/:token/payments | View payment status |
| GET | /vendor-portal/view/:token/rfqs | View RFQs |
| POST | /vendor-portal/view/:token/rfqs/:id/submit | Submit quote response |
WebSocket Events
Connect to the WebSocket endpoint for real-time updates:
wss://your-api-host/ws?token=YOUR_TOKENModule Cache Invalidation
Join a module room to receive real-time data change notifications:
{ "event": "join_module", "data": { "moduleKey": "accounting" } }The server emits module.invalidate when data changes, triggering client-side refetch.
Event Types
| Event | Payload | Description |
|---|---|---|
module.invalidate | { moduleKey, eventName } | Data changed in a module |
notification | Notification object | New notification for user |
user_joined | { userId, fullName, state } | User came online |
user_left | { userId } | User went offline |
dm:message | Message object | Direct message received |
dm:typing | { userId, userName } | User is typing |
Error Responses
All errors follow a consistent format:
{
"statusCode": 400,
"message": "Validation failed",
"errors": [
{ "field": "email", "message": "must be a valid email address" }
]
}| Status Code | Meaning |
|---|---|
| 400 | Bad Request — validation error |
| 401 | Unauthorized — invalid or expired token |
| 403 | Forbidden — insufficient permissions |
| 404 | Not Found — resource does not exist |
| 409 | Conflict — duplicate or state conflict |
| 429 | Too Many Requests — rate limit exceeded |
| 500 | Internal Server Error |