PlatformXeDocs
Get API Key

Modules API

Register and list permission modules.

Modules represent functional areas of your application. They are used by the Full authorization model to define action sets that can be assigned to roles.

Scope: permissions:manage

Rate limit: 500/hr

List modules

GET /api/v1/permissions/modules

Returns all registered modules for the tenant.

curl https://api.platformxe.com/api/v1/permissions/modules \
  -H "x-api-key: pxk_live_your_api_key_here"
const modules = await px.permissions.listModules();

Response

{
  "success": true,
  "data": {
    "modules": [
      {
        "id": "mod_bookings",
        "name": "BOOKINGS",
        "description": "Booking management",
        "actions": ["READ", "CREATE", "UPDATE", "DELETE", "LIST", "APPROVE"],
        "createdAt": "2026-03-15T08:00:00.000Z"
      }
    ]
  }
}

Register a module

POST /api/v1/permissions/modules

Registration is synchronous: the module is written before the response is sent, and the response carries the stored module.

FieldTypeRequiredDescription
idstringYesModule id, e.g. LT:PROPERTIES
appstringYesRegistering application, e.g. lettings
namestringYesDisplay name
descriptionstringNoHuman-readable description
pathsstring[]YesPaths this module covers (at least one)
curl -X POST https://api.platformxe.com/api/v1/permissions/modules \
  -H "Content-Type: application/json" \
  -H "x-api-key: pxk_live_your_api_key_here" \
  -d '{
    "id": "LT:PROPERTIES",
    "app": "lettings",
    "name": "Properties",
    "description": "Property listing management",
    "paths": ["properties", "properties/publish"]
  }'
await px.permissions.registerModule({
  id: 'LT:PROPERTIES',
  app: 'lettings',
  name: 'Properties',
  description: 'Property listing management',
  paths: ['properties', 'properties/publish'],
});

Response

HTTP 200:

{
  "success": true,
  "data": {
    "message": "Module registered",
    "module": {
      "id": "LT:PROPERTIES",
      "app": "lettings",
      "name": "Properties",
      "description": "Property listing management",
      "paths": ["properties", "properties/publish"],
      "organizationId": "org_abc123",
      "federatedKey": null,
      "createdAt": "2026-09-15T08:00:00.000Z"
    }
  }
}

Before 2026-09-15 this endpoint answered 202 and wrote the module in a background job, so a rejected write could still report success. It now answers 200 only after the write commits. Treat any 2xx as success.

Module limits by plan

PlanMax modules
Free5
Basic20
Pro50
EnterpriseUnlimited

The limit counts the modules your organization has registered. Registering a new module beyond your plan limit returns MODULE_LIMIT_EXCEEDED (HTTP 402). Re-registering a module your organization already owns is an update and is always allowed.

Module registration is idempotent. Re-registering a module id your organization owns updates its name, description and paths rather than creating a duplicate. A module id is owned by the organization that first registered it: another organization registering the same id receives CONFLICT (HTTP 409) and the existing module is left unchanged.

Tenant scope

Modules belong to the organization that registered them. GET returns only your organization's modules plus legacy modules that have no owner — never another organization's modules. Role module permissions can only reference modules visible to your organization.

Error responses

CodeDescription
BAD_REQUESTMissing name or empty actions array
CONFLICTThe module id is already registered by another organization (HTTP 409)
MODULE_LIMIT_EXCEEDEDModule count exceeds plan limit (HTTP 402)
FORBIDDENAPI key missing permissions:manage scope