Authentication
Permissions & Scopes
Roles, permissions, and integration scopes for the Store API.
Store integrations — authentication and scopes
Authentication
| Item | Value |
|---|---|
| HTTP header | X-API-Key — send your integration API key on every request |
| ASP.NET scheme | ApiKey |
| Controller | [Authorize(AuthenticationSchemes = "ApiKey")] on StoreIntegrationsController |
Unauthenticated or invalid key handling is defined by the host’s API key authentication handler (typically 401).
Address reference (public)
GET /api/v1/address-reference/provinces and GET /api/v1/address-reference/provinces/{code}/areas are AllowAnonymous — no X-API-Key. Same host as your integration; not under /store/integrations. Use them to resolve addressProvinceCode and addressAreaId before POST /orders. Shapes and query params: api-design.json → addressReference.
Scopes
-
Scopes are read from the
scopeclaim on the authenticated principal. -
If the required scope for an action is missing, the API returns 403 with body:
ApiResponsewithsuccess: false,message:Missing scope: <scope>, andcode: 403.
Scopes by area
The entire Store surface is now available under /api/v1/store/integrations with an X-API-Key.
Each endpoint requires the resource scope below; missing the scope returns 403. Grant a key only
the scopes it needs (least privilege) — …:read for GET, …:write for create/update/delete.
| Scope | Area / use |
|---|---|
orders:read / orders:write | Orders, order items, returns, status, QR, storefront OTP, delivery companies |
catalog:read / catalog:write | Products, product categories, inventory, warehouses, package sizes |
purchasing:read / purchasing:write | Suppliers, purchase orders (and attachments) |
customers:read / customers:write | Customer (CRM) records |
discounts:read / discounts:write | Discount codes (+ validate) and discount rules |
finance:read / finance:write | Expenses, wallet balance/transactions/bank details |
analytics:read | Sales/product/customer/expense/revenue analytics, dashboard summaries |
printing:read / printing:write | Invoice & label print templates |
store:read / store:write | Settings, profile, storefront (publish, templates, custom domain, sections, images) |
pos:read / pos:write | Cashier settings, sessions, pinned items |
tickets:read / tickets:write | Support tickets |
messaging:read / messaging:write | Website-chat hub token + conversations; social inbox conversations & channels |
delivery:read / delivery:write | Delivery providers, Al-Waseet, Boxy (orders, pickups, locations) |
subscription:read / subscription:write | Subscription, available plans, upgrade requests |
kyc:write | Upload KYC documents |
rbac:read / rbac:write | Staff users, roles, permissions (RBAC) |
apikeys:read / apikeys:write | List / create / revoke API keys |
mcp:read / mcp:write | MCP integration info, OAuth redirect URIs |
Security note:
rbac:*,apikeys:*,kyc:write, andsubscription:writeare powerful account-management scopes — only grant them to keys you fully trust, and prefer separate keys per integration.
Store JWT permissions (storefront)
Storefront endpoints use JWT bearer (not X-API-Key) with the following permission gates:
| Permission | Routes |
|---|---|
store.storefront.view | GET /api/v1/store/storefront, GET /api/v1/store/storefront/templates |
store.storefront.manage | PUT /api/v1/store/storefront, publish/unpublish, apply template |
Both permissions are granted to store_owner by default. store_staff receives store.storefront.view only.
Public storefront (no auth)
GET /api/v1/public/storefronts/{slug} and POST /api/v1/public/storefronts/{slug}/orders are [AllowAnonymous] — no X-API-Key or JWT. The store must have IsStorefrontPublished = true for these to return data (otherwise 404).
Response envelope
All integration actions return ApiResponse<T> in JSON:
success—trueon success.data— typed payload (seedtos,addressReference, andendpointsinapi-design.json).message— human-readable summary (optional on success, useful on errors).code— on errors, mirrors HTTP semantics (400, 401, 403, 404, 409, 422, 429, 500).errors— on validation failure, object map of field name → string[] messages.
HTTP status is chosen with RespondByErrorCode: success responses use 200; errors use the status matching code when present. Model binding / FluentValidation failures return 400 with ApiResponse and errors populated.
Linking
If the API key is not linked to a Store, many calls return 400 with a message such as "No store linked to this API key" (see StoreIntegrationsService).
Internal tenant claim (JWT and API keys)
For password/JWT users and store- or delivery-company-scoped API keys, the server may issue an internal claim organization_id (UUID) used for database row scoping. It is not required for integration clients to send this claim; it is derived from the authenticated store or delivery company. Platform admin and similar roles do not use this filter.
Store E-Commerce Module Permissions (JWT)
All permissions below apply to store JWT endpoints under /api/v1/store/*.
| Permission | What it gates | store_owner | store_staff |
|---|---|---|---|
store.product_categories.view | GET /categories, GET /categories/{id} | ✓ | ✓ |
store.product_categories.manage | POST/PUT/DELETE /categories | ✓ | — |
store.customers.view | GET /customers, GET /customers/{id} | ✓ | ✓ |
store.customers.manage | POST/PUT/DELETE /customers | ✓ | ✓ |
store.suppliers.view | GET /suppliers, GET /suppliers/{id} | ✓ | ✓ |
store.suppliers.manage | POST/PUT/DELETE /suppliers | ✓ | — |
store.purchase_orders.view | GET /purchase-orders, GET /purchase-orders/{id} | ✓ | ✓ |
store.purchase_orders.manage | POST/PUT/DELETE /purchase-orders, attachments | ✓ | — |
store.expenses.view | GET /expenses, GET /expenses/{id} | ✓ | ✓ |
store.expenses.manage | POST/PUT/DELETE /expenses | ✓ | — |
store.cashier.view | GET /cashier/settings, sessions, pinned items | ✓ | ✓ |
store.cashier.manage | PUT /cashier/settings, open/close sessions, pin items | ✓ | ✓ |
store.discounts.view | GET /discounts/rules, GET /discounts/codes, validate | ✓ | ✓ |
store.discounts.manage | POST/PUT/DELETE /discounts/rules, codes | ✓ | — |
store.shipping.view | GET /shipping/rules, GET /shipping/rules/{id} | ✓ | ✓ |
store.shipping.manage | POST/PUT/DELETE /shipping/rules | ✓ | — |
store.package_sizes.view | GET /package-sizes, GET /package-sizes/{id} | ✓ | ✓ |
store.package_sizes.manage | POST/PUT/DELETE /package-sizes | ✓ | — |
store.print_templates.view | GET /print-templates, GET /print-templates/{id} | ✓ | ✓ |
store.print_templates.manage | POST/PUT/DELETE /print-templates | ✓ | — |
store.settings.view | GET /settings | ✓ | ✓ |
store.settings.manage | POST /settings (init), PUT /settings | ✓ | — |
store.analytics.view | All POST /analytics/* endpoints | ✓ | ✓ |
store_staff summary: receives all *.view permissions + store.customers.manage + store.cashier.manage + store.analytics.view.
Social Messaging Permissions (JWT)
Permissions for the Social Messaging / CRM feature under /api/v1/store/social/*.
| Permission | What it gates | store_owner | store_staff |
|---|---|---|---|
store.social_channels.view | GET /social/channels | ✓ | — |
store.social_channels.manage | POST/PATCH/DELETE /social/channels, toggle-agent, rotate-token | ✓ | — |
store.conversations.view | GET /social/conversations, GET /social/conversations/{id} | ✓ | ✓ |
store.conversations.manage | POST /messages, resolve, reopen | ✓ | ✓ |
store_staff can read and reply to conversations but cannot connect, disconnect, or reconfigure channels.
MCP OAuth Scopes for Social Messaging
| Scope | MCP tools that require it |
|---|---|
messaging:read | list_conversations, get_conversation |
messaging:write | send_conversation_message, resolve_conversation |
These scopes are issued via the standard OAuth 2.0 PKCE flow (see store-mcp-server.md).
Source: DOCS/03-integrations/specs/store/auth-and-scopes.md