Skip to content

Quickstart

From sign-up to your first CMS page in about ten minutes. The examples use curl with jq in bash, and Invoke-RestMethod in PowerShell (Windows PowerShell 5.1 or PowerShell 7).

  1. Sign up in the Nimles portal and verify your email address. Creating a tenant needs a verified address.

  2. Request developer-beta access. In the portal, open My tenants, write a line about what you want to build and choose Request access. A Nimles platform administrator grants it to your account (the beta’s Tenant Creator role) and you get an email when you are in. Until then, the portal does not offer to create a tenant.

  3. Create a tenant. In the portal, open My tenants and choose Create a tenant. Give it a name. You become its Owner, and it gets a resource group named Default. You can create up to three tenants of your own.

  4. Create an API client. An API client is an OAuth 2.0 client in your tenant that signs in with the client credentials grant: you exchange its client id and secret for a short-lived access token. Open the tenant, go to its Developer section and choose Create API client. Pick a name, a role and how long the secret lives (30, 90 or 365 days). Use Contributor for this quickstart: it can read and change content, but not users, API clients or role assignments.

    The portal shows the client id and the secret. The secret is shown once: copy it now. The Developer section also shows your tenant id.

Exchange the client id and secret for an access token with the OAuth 2.0 client_credentials grant. Tokens live for one hour.

Terminal window
export NIMLES_TENANT_ID='<tenant id>'
export NIMLES_CLIENT_ID='<client id>'
export NIMLES_CLIENT_SECRET='<secret>'
NIMLES_TOKEN=$(curl -s "https://auth.nimles.com/tenant/$NIMLES_TENANT_ID/connect/token" \
-d grant_type=client_credentials \
--data-urlencode "client_id=$NIMLES_CLIENT_ID" \
--data-urlencode "client_secret=$NIMLES_CLIENT_SECRET" \
-d scope=nimles.user | jq -r .access_token)

The response is a standard token response:

{ "access_token": "eyJhbGciOi…", "token_type": "Bearer", "expires_in": 3600 }

Every API URL is https://api.nimles.com/{service}/api/tenant/{tenantId}/{Resource}. List the tenant’s CMS pages:

Terminal window
curl -s "https://api.nimles.com/cms/api/tenant/$NIMLES_TENANT_ID/Pages" \
-H "Authorization: Bearer $NIMLES_TOKEN" | jq

A new tenant has no pages yet, so the answer is an empty list:

{ "data": [], "fields": {} }

Content lives in a resource group, and a create names it in resourceGroupId. Find the id of the Default resource group, then create a page in it:

Terminal window
RESOURCE_GROUP_ID=$(curl -s "https://api.nimles.com/identity/api/tenant/$NIMLES_TENANT_ID/ResourceGroups" \
-H "Authorization: Bearer $NIMLES_TOKEN" | jq -r '.data[] | select(.name == "Default") | .id')
curl -s -i "https://api.nimles.com/cms/api/tenant/$NIMLES_TENANT_ID/Pages" \
-H "Authorization: Bearer $NIMLES_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"resourceGroupId": "'"$RESOURCE_GROUP_ID"'",
"pageType": "Page",
"title": "Hello, Nimles",
"uniqueName": "hello-nimles"
}'

The API answers 201 Created with the new page’s id in the body. Location is the page’s path within the CMS service, without the /cms prefix that api.nimles.com routes by, so it is not a URL you can call as it is: use data.id from the body (as the examples do).

HTTP/1.1 201 Created
Location: /api/tenant/{tenantId}/Pages/bf8a927c-96dc-43ad-8195-4331246bbde1
{"data":{"id":"bf8a927c-96dc-43ad-8195-4331246bbde1"},"fields":{}}
  • title, pageType and uniqueName are required.
  • uniqueName is the page’s URL slug, normalised to lower-case letters, digits and -: _ and spaces become -, å, ä and ö become a, a and o, and other characters are dropped, so Hello_World is stored as hello-world. Send "" to have it made from the title.
  • pageType is a word the site that renders the page interprets. The Nimles storefront understands Page (an ordinary page), FirstPage (the start page), About, Contact, Map and SignIn.
  • The page starts as a Draft. PUT …/Pages/{id}/publish publishes it.
  • Reads catch up with writes within moments: a GET right after the create can still answer 404, or the old version after a change.

Change members with JSON Patch. Replace the title and add a summary:

Terminal window
PAGE_ID='<the id from the create>'
curl -s -i -X PATCH "https://api.nimles.com/cms/api/tenant/$NIMLES_TENANT_ID/Pages/$PAGE_ID" \
-H "Authorization: Bearer $NIMLES_TOKEN" \
-H "Content-Type: application/json" \
-d '[
{ "op": "replace", "path": "/title", "value": "Hello again, Nimles" },
{ "op": "add", "path": "/summary", "value": "My first page through the API." }
]'

The API answers 204 No Content. A mistake answers 422 with the errors by path; see API conventions.

In PowerShell a 4xx answer throws, and the error body is in $_.ErrorDetails.Message:

Terminal window
try {
Invoke-RestMethod -Method Patch -Headers $headers `
-Uri "https://api.nimles.com/cms/api/tenant/$TenantId/Pages/$pageId" `
-ContentType 'application/json; charset=utf-8' `
-Body ([Text.Encoding]::UTF8.GetBytes($patch))
} catch {
$_.Exception.Response.StatusCode # e.g. UnprocessableEntity
$_.ErrorDetails.Message # the JSON body, with the errors by path
}
  • Concepts: tenants, resource groups and roles.
  • Authentication: token lifetime, rotating secrets.
  • GraphQL: paged and filtered reads.
  • The API reference in the sidebar, starting with CMS.