Domains
Use these endpoints to compose and roll back domains, and to read the domains that your authorization engine fetches.
Domains are handled by two services:
- The Hub service composes and rolls back domains. These requests use the
/api/domainspath and theX-Project-Idheader. - The domain manager stores the composed domains and serves them to authorization engines. These requests use the
/api/admpath. The project ID is part of the path, as the namespace, so these requests do not need theX-Project-Idheader.
Composing and rolling back a domain require the Project editor role. Reading domains requires the Domain viewer role or higher. Read Permissions for details.
Domain changes are applied immediately and are not staged in My workspace. Domains only use changes that have been saved to the project, so promote your workspace before you compose a domain.
Compose and roll back
| Method | Path | Description |
|---|---|---|
POST | /api/domains/{domainName}/compose | Compose a domain from the project's policies. |
POST | /api/domains/{domainName}/rollback/{id} | Roll a domain back to an earlier version. |
Compose a domain
Composing a domain transpiles the ALFA policies of the project's policy package and packages them, together with the attribute definitions, attribute connectors, and cache settings you send, into the domain configuration that authorization engines use. Composing with the name of an existing domain creates a new version of that domain.
curl -X POST "https://<authorization-hub-url>/api/domains/production/compose" \
-H "Authorization: Bearer <access_token>" \
-H "X-Project-Id: <project-id>" \
-H "Content-Type: application/json" \
-d @compose.json
{
"mainPolicyId": "access.root",
"policyPackageName": "policypackage",
"metadata": { "description": "Production domain" },
"attributes": {
"user.department": { "xacmlId": "user.department", "category": "AccessSubject", "datatype": "string" },
"resource.type": { "xacmlId": "resource.type", "category": "Resource", "datatype": "string" }
},
"attributeCache": {
"user.department": { "timeToLive": "3600 s", "maxItems": 1000 }
},
"decisionParameters": { "partialEvaluationThreshold": 100 }
}
| Field | Required | Description |
|---|---|---|
mainPolicyId | Yes | The fully qualified ALFA name of the policy entry point, for example access.root. |
policyPackageName | Yes | The policy package to compose. Use policypackage, the package that the interface uses. The ALFA files are always taken from this package. |
metadata | No | Free-form string values stored with the domain. The interface stores the domain description here. |
attributes | No | The attribute definitions that the domain uses. See Attributes. |
attributeConnectors | No | The attribute connectors to include. See Attribute connectors. |
attributeCache | No | The cache settings, keyed by attribute name. Each entry has a timeToLive, in the format <seconds> s, and maxItems. |
decisionParameters | No | partialEvaluationThreshold, a number between 2 and 9999. |
The domain name in the path must not be blank, cannot contain control characters, and can have up to 500 characters.
The Authorization Hub interface builds this request for you from the Dictionary, the attribute connectors you select, and the cache profiles. When you call the API, your script must assemble these parts. To see what a working request contains, compare it with a domain you composed in the interface.
Attributes
Include an entry for every attribute that the policies and the selected attribute connectors use. The key is the attribute's fully qualified name, and each entry has the following fields:
| Field | Description |
|---|---|
xacmlId | The attribute's xacmlId, as returned by the Dictionary. It is the fully qualified name if none was set. |
category | AccessSubject, Resource, Action, or Environment. These correspond to the dictionary categories subjectCat, resourceCat, actionCat, and environmentCat. |
datatype | The attribute type, such as string. |
If an attribute that an attribute connector provides, or uses as a key, has no definition, the compose fails with the message attribute-definitions are missing.
Attribute connectors
attributeConnectors is an array. Copy the following fields of each attribute connector from its response: name, className, configuration, and providedAttributes.
Response
A successful compose returns 201:
{
"id": "7e0c4a52-91d3-4b6f-8f0e-2c5d7a1b9e33",
"name": "production",
"projectId": "e00f12c8-8f3a-40ac-81a7-5a762abc7288",
"kind": "AuthorizationDomain",
"createdBy": "a1b2c3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d",
"metadata": { "description": "Production domain" }
}
id identifies this version of the domain. Use it to roll back later.
Compose errors
| Status | Cause |
|---|---|
400 | A mainPolicyId or policyPackageName is missing or blank. Authorization Hub rejects the request with INVALID_REQUEST as the errorCode, and the message names the field. |
400 | The domain manager rejects the request. The error has EXTERNAL_ERROR as its errorCode, and its messages describe each problem, such as ALFA syntax errors with their file and line, a mainPolicyId that does not match a policy, missing attribute definitions, or a threshold outside the allowed range. |
403 | The caller's role does not allow the request. |
404 | The policy package does not exist. |
503 | The domain manager is unavailable. |
Roll back a domain
curl -X POST "https://<authorization-hub-url>/api/domains/production/rollback/<version-id>" \
-H "Authorization: Bearer <access_token>" \
-H "X-Project-Id: <project-id>"
The version-id is the domainId of an earlier version, from the domain history. The response is 200 with no body. Rolling back to the current version is not allowed and returns 409. An unknown domain or version returns 404.
Both operations are recorded in the activity feed: a compose as a creation and a rollback as an update.
Read domains
These requests use the project ID as the namespace, in the path:
| Method | Path | Description |
|---|---|---|
GET | /api/adm/namespaces/{projectId}/names | List the domain names. |
GET | /api/adm/namespaces/{projectId}/names/{domainName}/domain | Get a domain. |
GET | /api/adm/namespaces/{projectId}/names/{domainName}/history | List the versions of a domain. |
GET | /api/adm/namespaces/{projectId}/names/{domainName}/history/metadata | List the versions of a domain, with their metadata. |
GET | /api/adm/namespaces/{projectId}/domains/metadata | List the metadata of all domains in the project. |
Domain names are returned as { "names": ["production", "staging"] }. A project without domains returns an empty list.
The domain manager Swagger UI also lists lower-level endpoints, such as storing and copying domains and managing a separate policy package. Authorization Hub does not use them: manage policies through the policy endpoints and create domains by composing them.
Get a domain
This is the endpoint that authorization engines call. Its URL is the domain's API URL, which you can copy from the Domains page.
curl -X GET "https://<authorization-hub-url>/api/adm/namespaces/<project-id>/names/production/domain" \
-H "Authorization: Bearer <access_token>"
The response contains everything the engine needs: the policies as XACML in policy.xacmlSpecifications, the mainPolicyId, the attributes, the attributeConnectors, the attributeCache, and the decisionParameters. By default, the ALFA source files and the internal metadata entries (those starting with _ADM_) are omitted. Add ?extended=true to include them.
The response has an ETag header. To avoid downloading an unchanged domain, send it back in an If-None-Match header. The response is 304 Not Modified if the domain has not changed.
curl -X GET "https://<authorization-hub-url>/api/adm/namespaces/<project-id>/names/production/domain" \
-H "Authorization: Bearer <access_token>" \
-H 'If-None-Match: "<etag>"'
An unknown domain returns 404.
The client must be a member of the project, and a Domain viewer is enough. Read Client management to create a client for your authorization engine.
Domain history
GET .../history returns the versions of a domain, newest first. Each entry has the domainId of the version and its timestamp, as an ISO-8601 date and time:
{
"apiNameHistoryRecords": [
{ "domainId": "7e0c4a52-91d3-4b6f-8f0e-2c5d7a1b9e33", "timestamp": "2026-10-13T09:15:30.123456Z[UTC]" }
]
}
GET .../history/metadata returns the same list, with the metadata of each version in apiNameHistoryMetadataRecords. This endpoint requires the Project viewer role or higher.
Domain metadata
GET .../domains/metadata returns an array with the metadata of every domain in the project:
| Key | Description |
|---|---|
_ADM_ID_ | The ID of the current version. |
_ADM_NAME_ | The domain name. |
_ADM_NAMESPACE_ | The project ID. |
_ADM_CREATED_BY_ | The ID of the user or client that composed this version. |
_ADM_KIND_ | AuthorizationDomain. |
description | The description, if one was set. |
Domain errors
Requests to /api/adm return the domain manager error format.
| Status | Cause |
|---|---|
400 | The namespace or domain name is invalid, or a version ID is not a UUID. |
404 | The domain does not exist. |
409 | A rollback to the current version was attempted. |