Skip to content

REST API

Entity endpoints

Every entity generates a standard set of JSON:API endpoints:

MethodPathOperation
GET/api/v{n}/{entities}List with filtering, sorting, pagination
POST/api/v{n}/{entities}Create
GET/api/v{n}/{entities}/{id}Get by ID
PATCH/api/v{n}/{entities}/{id}Update
DELETE/api/v{n}/{entities}/{id}Delete
GET/api/v{n}/{entities}/{id}/relationships/{rel}Get relationship
POST/api/v{n}/{entities}/{id}/relationships/{rel}Add to relationship
PATCH/api/v{n}/{entities}/{id}/relationships/{rel}Replace relationship
DELETE/api/v{n}/{entities}/{id}/relationships/{rel}Remove from relationship

{entities} is the plural form of the entity name (camelCase, e.g. invoices, lineItems). The v{n} segment corresponds to a declared API version.

All requests to entity endpoints must use:

  • Authorization: Bearer <token> or X-API-Key: <key>
  • Content-Type: application/vnd.api+json for write requests

JSON:API features

Filtering (RSQL)

Use the filter query parameter with RSQL syntax:

GET /api/v1/invoices?filter=status==PAID
GET /api/v1/invoices?filter=amount=gt=1000
GET /api/v1/invoices?filter=status==DRAFT,status==ISSUED
GET /api/v1/invoices?filter=status==PAID;amount=gt=500
OperatorMeaning
==equals
!=not equals
=gt=greater than
=ge=greater than or equal
=lt=less than
=le=less than or equal
=in=in list: status=in=(PAID,ISSUED)
=out=not in list
=like=SQL LIKE pattern: name=like=Acme%
;AND
,OR

Sorting

GET /api/v1/invoices?sort=amount          # ascending
GET /api/v1/invoices?sort=-amount         # descending
GET /api/v1/invoices?sort=-status,amount  # multi-field

Pagination

Page-number based pagination:

GET /api/v1/invoices?page[number]=2&page[size]=10

The response meta.pagination object contains:

json
{
  "meta": {
    "pagination": {
      "number": 2,
      "size": 10,
      "totalPages": 5,
      "totalRecords": 48
    }
  }
}

Default page size is 20. Maximum is 100.

Sparse fieldsets

Request only specific attributes to reduce payload size:

GET /api/v1/invoices?fields[invoice]=amount,status

Compound documents (include)

Include related resources in a single response:

GET /api/v1/invoices?include=customer
GET /api/v1/invoices?include=customer,lineItems

Related resources appear in the included array. Relationships in data[].relationships contain data.type and data.id pointers.

Atomic operations

Multiple mutations in a single all-or-nothing request using the application/vnd.api+json;ext="https://jsonapi.org/ext/atomic" content type:

json
{
  "atomic:operations": [
    {
      "op": "add",
      "data": { "type": "invoice", "attributes": { "amount": 100, "status": "DRAFT" }, "relationships": { "customer": { "data": { "type": "customer", "id": "1" } } } }
    },
    {
      "op": "update",
      "ref": { "type": "customer", "id": "1" },
      "data": { "type": "customer", "attributes": { "name": "Updated Name" } }
    }
  ]
}

All operations succeed or all are rolled back.


Request and response shapes

Create request

POST /api/v1/invoices
Content-Type: application/vnd.api+json

{
  "data": {
    "type": "invoice",
    "attributes": {
      "amount": 4999.00,
      "status": "DRAFT"
    },
    "relationships": {
      "customer": {
        "data": { "type": "customer", "id": "1" }
      }
    }
  }
}

Response

json
{
  "data": {
    "type": "invoice",
    "id": "a1b2c3d4-...",
    "attributes": {
      "amount": 4999.00,
      "status": "DRAFT"
    },
    "relationships": {
      "customer": {
        "data": { "type": "customer", "id": "1" }
      },
      "lineItems": {
        "data": []
      }
    }
  }
}

Error response

json
{
  "errors": [
    {
      "status": "400",
      "title": "Bad Request",
      "detail": "ValidateInvoice hook rejected the request"
    }
  ]
}

Optimistic locking headers

When optimisticLocking: true on an entity:

  • Every response includes ETag: "0" (the current version number)
  • Mutations (PATCH, PUT, DELETE) must include If-Match: "0"
  • Stale version → 412 Precondition Failed
  • Missing header → 428 Precondition Required

Management endpoints

Auth (/auth)

MethodPathAuth requiredDescription
POST/auth/loginNoUsername/password → JWT + refresh token
POST/auth/refreshNoRotate refresh token
POST/auth/logoutNoRevoke refresh token family
GET/auth/meYesCurrent user info
PATCH/auth/meYesUpdate own profile (user-editable keys only)
POST/auth/change-passwordYesChange password
POST/auth/tokenNoService account token
POST/auth/me/api-keysYesCreate a personal API key (delegated from caller)
GET/auth/me/api-keysYesList own personal API keys
POST/auth/me/api-keys/{keyId}/disableYesDisable own personal API key
POST/auth/accept-inviteNoRedeem an invite token and create the account

Tenant management (/manage/tenants) — POOL mode only

MethodPathRequired role
POST/manage/tenantsSuperAdmin
GET/manage/tenantsSuperAdmin
GET/manage/tenants/{id}SuperAdmin
PATCH/manage/tenants/{id}SuperAdmin
DELETE/manage/tenants/{id}SuperAdmin
POST/manage/tenants/{id}/usersSuperAdmin or same-tenant TenantAdmin
GET/manage/tenants/{id}/usersSuperAdmin or same-tenant TenantAdmin
DELETE/manage/tenants/{id}/users/{uid}SuperAdmin or same-tenant TenantAdmin
PATCH/manage/tenants/{id}/users/{uid}SuperAdmin or same-tenant TenantAdmin
PUT/manage/tenants/{id}/users/{uid}/rolesSuperAdmin or same-tenant TenantAdmin
POST/manage/tenants/{id}/tenant-admins/{uid}SuperAdmin
DELETE/manage/tenants/{id}/tenant-admins/{uid}SuperAdmin
POST/manage/tenants/{id}/invitesSuperAdmin or same-tenant TenantAdmin
GET/manage/tenants/{id}/invitesSuperAdmin or same-tenant TenantAdmin
DELETE/manage/tenants/{id}/invites/{inviteId}SuperAdmin or same-tenant TenantAdmin
POST/manage/tenants/{id}/service-accountsSuperAdmin or same-tenant TenantAdmin
GET/manage/tenants/{id}/service-accountsSuperAdmin or same-tenant TenantAdmin
POST/manage/tenants/{id}/service-accounts/{accountId}/disableSuperAdmin or same-tenant TenantAdmin
POST/manage/tenants/{id}/service-accounts/{accountId}/rotate-secretSuperAdmin or same-tenant TenantAdmin
GET/manage/tenants/{id}/personal-api-keysSuperAdmin or same-tenant TenantAdmin
POST/manage/tenants/{id}/personal-api-keys/{keyId}/revokeSuperAdmin or same-tenant TenantAdmin
GET/manage/tenants/{id}/settings/personal-api-keysSuperAdmin or same-tenant TenantAdmin
PUT/manage/tenants/{id}/settings/personal-api-keysSuperAdmin or same-tenant TenantAdmin
GET/manage/settings/personal-api-keysSuperAdmin
PUT/manage/settings/personal-api-keysSuperAdmin

Other framework endpoints

MethodPathDescription
GET/manage/auditQuery audit log (SuperAdmin or TenantAdmin)
GET/actuator/healthSpring Boot health check
GET/actuator/metricsMetrics (if exposed)
GET/manage/migrations/statusMigration status