Skip to content

API conventions

Every Nimles service follows the same conventions, so what you learn on one applies to all of them.

https://api.nimles.com/{service}/api/tenant/{tenantId}/{Resource}[/{id}[/{action}]]
  • {service} is the service prefix: identity, cms, media, pim, e-commerce, directory, communication, crm, lms, accounting, property-management, ai or work-management.
  • {Resource} is plural, such as Pages, Products or Orders. Routes are not case-sensitive.
  • Ids are GUIDs.
Request Means
GET {Resource} List (with filters as query parameters, such as ?ids=…&ids=…)
GET {Resource}/{id} Read one
POST {Resource} Create
PUT {Resource}/{id} Update with the whole item
PATCH {Resource}/{id} Change some members, with JSON Patch
DELETE {Resource}/{id} Delete
PUT {Resource}/{id}/{action} An action, such as publish on a page or submit on an order

Bodies are JSON, with camelCase members. Times are UTC in ISO 8601. Responses wrap their content in data:

{ "data": { "id": "bf8a927c-…", "title": "Hello, Nimles" }, "fields": {} }

A list is { "data": [ … ] }. fields is always there and normally empty. Members whose value is null are left out of responses.

Every item has the platform members id, tenantId, creatorId, createdDate, lastModified and version, which the service sets.

Code When
200 OK A read, or a change that returns the item
201 Created A create. The body is { "data": { "id": … } } (or the whole item). Location is the item’s path within the service, /api/tenant/{tenantId}/{Resource}/{id}, without the /{service} prefix api.nimles.com routes by: use the id from the body
204 No Content A change or delete without a body. Most PUT, PATCH, DELETE and actions answer this
400 Bad Request A malformed request
401 Unauthorized No token, or an expired or invalid one (no body)
403 Forbidden The caller has no role that allows the action at this scope. Some lists answer only what the caller may read instead
404 Not Found No such item in the tenant
409 Conflict The item kept changing under concurrent writes; read it again and retry
422 Unprocessable Entity The body or the change is invalid; see Errors
429 Too Many Requests A rate limit

Validation errors answer 422 with a ValidationProblemDetails: the messages by member, or by JSON Pointer for a patch.

{
"title": "One or more validation errors occurred.",
"status": 422,
"errors": { "Title": ["'Title' must not be empty."] }
}

A body that cannot be read as the expected type at all (wrong JSON, a missing required member) also answers 422, keyed by member or $:

{
"$": ["JSON deserialization for type '…PageCreateModel' was missing required properties including: 'title', 'uniqueName'."]
}

404 answers an RFC 9457 problem (application/problem+json) with type, title and status. 403 answers either without a body or with a problem whose detail names the action you lack:

{
"type": "https://datatracker.ietf.org/doc/html/rfc9110#section-15.5.4",
"title": "Forbidden",
"status": 403,
"detail": "The principal does not have permission to perform the action 'Nimles.Cms/pages/read'."
}

PATCH {Resource}/{id} takes a JSON Patch (RFC 6902) document: an array of add, remove, replace, move, copy and test operations, sent as application/json.

[
{ "op": "test", "path": "/title", "value": "Hello, Nimles" },
{ "op": "replace", "path": "/title", "value": "Hello again, Nimles" },
{ "op": "add", "path": "/titleLocalized/sv", "value": "Hej igen, Nimles" },
{ "op": "remove", "path": "/summary" }
]
  • The operations apply in order, and all or none: if one fails, nothing changes. A failed test answers 422 with the path, which makes test a cheap check that a member still has the value you read.
  • A patch can change exactly what a PUT can change, and must pass the same validation.
  • The platform members cannot be patched: id, tenantId, resourceGroupId, organizationId, createdDate, creatorId, lastModified, version, accessibility, permissions, relations and isDeleted (test on them is refused too). Each answers 422, for example { "errors": { "/id": ["'/id' cannot be patched."] } }.
  • Items in lists keep their ids: change a list item at /elements/0/content rather than replacing the whole list.
  • A patch that changes nothing succeeds and stores nothing.

PUT sends the whole item: members you leave out are generally cleared. Use PATCH to change a few members.

REST lists answer every matching item in one response; there is no paging, sorting or text search. Filter with the query parameters each list takes (often ids, resourceGroupId or a parent id).

For paging and filtering, use GraphQL on CMS, PIM, Ecommerce and Directory: pages of up to 100 items with cursors.

Writes are stored first and then projected into the read models the GETs and lists answer from. A read right after a write can, for a moment, miss a new item or show the previous version. Use the id from the create’s answer rather than looking the item up in a list, and expect a short delay before lists show a change.

The API sends no CORS headers: browsers cannot call it from another origin. That is on purpose: the secret of an API client (an OAuth 2.0 client in your( )tenant that exchanges its client id and secret for a short-lived access token) must never be in a browser, and a( )user’s token is better kept on a server too.

Call the API from your backend, and give your web app its own endpoints (a backend for frontend). Public sites built on Nimles work the same way: their server reads content with a token and renders or proxies it.