Skip to content

REST API

Create an API key

POST/v1alpha1/admin/keyskeys.write

Creates an API key and returns the generated credential string and key metadata. The full secret credential is returned only in this response because credentials are stored only as hashes. A lost credential cannot be recovered and must be replaced. Server logs record the key id, never the credential value.

When a key is created, roles are expanded into their constituent permissions. Only the resulting permissions are stored in the key. Existing keys do not change permissions if role definitions change in later software versions.

A key created on one node works on all nodes immediately because nodes look up unseen keys without delay. Served by whichever node receives the request.

Body

KeyDefinitionRequired

What a key should be allowed to do. See Permissions.

descriptionstring
What the key is for, so whoever lists the keys later can tell them apart. Read by nobody but a human.
Example
"the search backend"
grantsGrantDefinition[]required
What the key may do, evaluated as a union: a request is allowed if any grant permits it, and there are no deny rules. At least one grant is required, as a key with none could do nothing.
Example
{
"role": "reader",
"indexes": [
"products"
]
}
3 properties
rolestring
Shorthand for a set of permissions. reader grants search and indexes.read. writer adds documents.read, documents.write, documents.delete, and indexes.commit, but not indexes.write. admin grants all permissions, including key management. When a key is created, roles are expanded into their constituent permissions. Only the resulting permissions are stored in the key. Existing keys do not change permissions if role definitions change in later software versions.
Values
"reader", "writer", "admin"
Example
"reader"
permissionsstring[]
Permissions by name, added to whatever role specifies. An unknown permission name returns auth:key:permission_unknown.
indexesstring[]
Index names or prefix patterns the permissions apply to. An index pattern is either an exact index name or a prefix followed by *; a single * matches all indexes. Required for index-scoped permissions and ignored for deployment-scoped permissions. Generations are named index@generation: products matches the index but no generation of it, products@* matches every generation but not the index itself, and products* matches both.
expiresAtstring
An ISO 8601 timestamp string defining when the key expires. If omitted, the key does not expire.
Example
"2027-01-01T00:00:00Z"

Responses

201
The key was created. The credential in this response is the only copy returned.
CreatedKey

A newly created key. This is the only response its credential ever appears in.

credentialstring
The generated credential, presented as Authorization: Bearer. Only a hash of it is stored, so this response is the only chance to keep it. A lost credential cannot be recovered and must be replaced.
Example
"exok_4ff6b760264c1918_ePQcdT1O9HSATZoXfDbT8hhHGsP9VpZH"
The key as a listing will show it from now on.
Example
{
"id": "4ff6b760264c1918",
"description": "the search backend",
"grants": [
{
"permissions": [
"indexes.read",
"search"
],
"indexes": [
"products"
]
}
],
"createdAt": "2026-08-16T12:09:33.198275Z",
"expiresAt": "2027-01-01T00:00:00Z"
}
5 properties
idstring
Key identifier. Server logs record the key ID, never the credential value.
Example
"4ff6b760264c1918"
descriptionstring
A string describing the key.
Example
"the search backend"
grantsGrant[]
Grants assigned to the key, with roles expanded into their constituent permissions.
Example
{
"permissions": [
"indexes.read",
"search"
],
"indexes": [
"products"
]
}
2 properties
permissionsstring[]
Permission names, in sorted order.
indexesstring[]
Index names and prefix patterns in the order specified.
createdAtstring
An ISO 8601 timestamp string defining when the key was created.
Example
"2026-08-16T12:09:33.198275Z"
expiresAtstring
An ISO 8601 timestamp string defining when the key expires. null for a key that does not expire.
Example
"2027-01-01T00:00:00Z"
400
The request body is missing, or the key definition failed validation. All validation errors are reported.
ErrorResponse

The body of every failed request. Error codes use colon-separated namespaces such as index:field:name_invalid, are stable across API versions, and are never renamed or reused, so clients match on code rather than on message. See Errors.

codestring
Identifies the failure type. For validation failures, this is validation and the individual problems are listed in errors. For all other failures, this matches the code of the single entry in errors.
Example
"validation"
messagestring
Human-readable message for log output. Match on code rather than on message. When a validation failure contains one problem, this is that problem's message. When it contains several, it reads Request contains N errors.
Example
"Request contains 2 errors"
All problems found in the request. A validation failure reports every field with a problem, so a caller can fix them in one pass rather than one request at a time.
Example
{
"code": "index:field:primary_key:multiple_unsupported",
"message": "Field `id` is marked as a primary key and multiple, primary keys can not have multiple values",
"path": "id"
}
4 properties
codestring
The error code identifying this specific problem.
Example
"index:field:primary_key:multiple_unsupported"
messagestring
Human-readable description of this problem.
Example
"Field `id` is marked as a primary key and multiple, primary keys can not have multiple values"
pathstring
Location of the offending value in the request, such as fields.title or documents[1].nonexistent. Names join with ., one element of a list reads [n] counted from zero, and a key of a free-form map such as metadata goes in brackets and double quotes when it holds a dot or a bracket, as metadata["build.sha"]. A field inside an object field carries its own dotted path, so a path here reaches a field the same way a query does. Omitted when the problem applies to the request as a whole. See API conventions.
Example
"id"
argumentsmap of string
The values the message was rendered with, so a client can render a message of its own from the code.
1 property
<key>string
Error codes
request:body_required
The request carries no body.
auth:key:role_unknown
The definition names a role this version does not have.
auth:key:permission_unknown
The definition names a permission this version does not have.
auth:key:grants_required
The definition holds no grant, so the key could do nothing.
auth:key:permissions_required
A grant names neither a role nor a list of permissions.
auth:key:indexes_required
A grant holds a permission that is about one index and does not say which indexes it covers.
auth:key:index_pattern_invalid
An entry of `indexes` is neither an index name nor a prefix followed by `*`.
auth:key:indexes_unsupported
A grant names `indexes` and holds no permission that is about one index, so the patterns would narrow nothing.
auth:key:expiry_invalid
`expiresAt` is not an ISO 8601 timestamp.
auth:key:expiry_in_past
`expiresAt` has already passed, so the key would be lapsed from the moment it was created.
401
The request carries no credential this node accepts. Absent, malformed, unknown and lapsed keys are all answered alike, so a refusal cannot be used to find out which keys exist. The response carries WWW-Authenticate: Bearer.
ErrorResponse

The body of every failed request. Error codes use colon-separated namespaces such as index:field:name_invalid, are stable across API versions, and are never renamed or reused, so clients match on code rather than on message. See Errors.

codestring
Identifies the failure type. For validation failures, this is validation and the individual problems are listed in errors. For all other failures, this matches the code of the single entry in errors.
Example
"validation"
messagestring
Human-readable message for log output. Match on code rather than on message. When a validation failure contains one problem, this is that problem's message. When it contains several, it reads Request contains N errors.
Example
"Request contains 2 errors"
All problems found in the request. A validation failure reports every field with a problem, so a caller can fix them in one pass rather than one request at a time.
Example
{
"code": "index:field:primary_key:multiple_unsupported",
"message": "Field `id` is marked as a primary key and multiple, primary keys can not have multiple values",
"path": "id"
}
4 properties
codestring
The error code identifying this specific problem.
Example
"index:field:primary_key:multiple_unsupported"
messagestring
Human-readable description of this problem.
Example
"Field `id` is marked as a primary key and multiple, primary keys can not have multiple values"
pathstring
Location of the offending value in the request, such as fields.title or documents[1].nonexistent. Names join with ., one element of a list reads [n] counted from zero, and a key of a free-form map such as metadata goes in brackets and double quotes when it holds a dot or a bracket, as metadata["build.sha"]. A field inside an object field carries its own dotted path, so a path here reaches a field the same way a query does. Omitted when the problem applies to the request as a whole. See API conventions.
Example
"id"
argumentsmap of string
The values the message was rendered with, so a client can render a message of its own from the code.
1 property
<key>string
Error codes
auth:unauthenticated
The request carries no credential this node accepts.
403
The API key does not have the keys.write permission.
ErrorResponse

The body of every failed request. Error codes use colon-separated namespaces such as index:field:name_invalid, are stable across API versions, and are never renamed or reused, so clients match on code rather than on message. See Errors.

codestring
Identifies the failure type. For validation failures, this is validation and the individual problems are listed in errors. For all other failures, this matches the code of the single entry in errors.
Example
"validation"
messagestring
Human-readable message for log output. Match on code rather than on message. When a validation failure contains one problem, this is that problem's message. When it contains several, it reads Request contains N errors.
Example
"Request contains 2 errors"
All problems found in the request. A validation failure reports every field with a problem, so a caller can fix them in one pass rather than one request at a time.
Example
{
"code": "index:field:primary_key:multiple_unsupported",
"message": "Field `id` is marked as a primary key and multiple, primary keys can not have multiple values",
"path": "id"
}
4 properties
codestring
The error code identifying this specific problem.
Example
"index:field:primary_key:multiple_unsupported"
messagestring
Human-readable description of this problem.
Example
"Field `id` is marked as a primary key and multiple, primary keys can not have multiple values"
pathstring
Location of the offending value in the request, such as fields.title or documents[1].nonexistent. Names join with ., one element of a list reads [n] counted from zero, and a key of a free-form map such as metadata goes in brackets and double quotes when it holds a dot or a bracket, as metadata["build.sha"]. A field inside an object field carries its own dotted path, so a path here reaches a field the same way a query does. Omitted when the problem applies to the request as a whole. See API conventions.
Example
"id"
argumentsmap of string
The values the message was rendered with, so a client can render a message of its own from the code.
1 property
<key>string
Error codes
auth:forbidden
The key is accepted but does not hold the `keys.write` permission.
409
The key could not be stored. The stored keys are unchanged.
ErrorResponse

The body of every failed request. Error codes use colon-separated namespaces such as index:field:name_invalid, are stable across API versions, and are never renamed or reused, so clients match on code rather than on message. See Errors.

codestring
Identifies the failure type. For validation failures, this is validation and the individual problems are listed in errors. For all other failures, this matches the code of the single entry in errors.
Example
"validation"
messagestring
Human-readable message for log output. Match on code rather than on message. When a validation failure contains one problem, this is that problem's message. When it contains several, it reads Request contains N errors.
Example
"Request contains 2 errors"
All problems found in the request. A validation failure reports every field with a problem, so a caller can fix them in one pass rather than one request at a time.
Example
{
"code": "index:field:primary_key:multiple_unsupported",
"message": "Field `id` is marked as a primary key and multiple, primary keys can not have multiple values",
"path": "id"
}
4 properties
codestring
The error code identifying this specific problem.
Example
"index:field:primary_key:multiple_unsupported"
messagestring
Human-readable description of this problem.
Example
"Field `id` is marked as a primary key and multiple, primary keys can not have multiple values"
pathstring
Location of the offending value in the request, such as fields.title or documents[1].nonexistent. Names join with ., one element of a list reads [n] counted from zero, and a key of a free-form map such as metadata goes in brackets and double quotes when it holds a dot or a bracket, as metadata["build.sha"]. A field inside an object field carries its own dotted path, so a path here reaches a field the same way a query does. Omitted when the problem applies to the request as a whole. See API conventions.
Example
"id"
argumentsmap of string
The values the message was rendered with, so a client can render a message of its own from the code.
1 property
<key>string
Error codes
storage:unavailable
The node is not configured with key storage.
storage:io_error
Key storage answered with an error. Send the request again.
storage:conflict
Other nodes kept changing the stored keys. The stored keys are unchanged; send the request again.

Authorization

Permission
keys.write
Checked on
The deployment, not one index
Roles
admin

An API key sent as a bearer token, such as Authorization: Bearer exok_4ff6b760264c1918_ePQcdT1O9HSATZoXfDbT8hhHGsP9VpZH. A key carries grants that pair permissions with index patterns; the permission each endpoint needs is named beside it. Nodes running with EXOFIND_AUTH_MODE=none accept requests without a credential, and a node with EXOFIND_AUTH_ANONYMOUS_KEY set serves requests that carry none with the permissions of that key.

Exofind is built by Level Four AB and is available under the Apache License 2.0.