Skip to main content

Advanced identity search via API

Advanced identity search allows you to perform full-text search on identity traits, public and admin metadata, combined with arbitrary filters and faceting.

Need help?

Getting started

Ory exposes an advanced Identity Search API that is compatible with the Typesense search protocol. You can use existing Typesense SDKs to interact with it. Pass your Ory Network API key where you would normally pass the Typesense API key, and use the following base URL:

https://{your-ory-slug}.projects.oryapis.com/admin/preview/search/v0beta1

and set the collection name to identities-{your-project-id}.

See the following examples for how to configure and use the Typesense SDKs to search for identities.

export ORY_API_KEY="ory_pat_XXXXXXXXXXXXXXXX"
export COLLECTION="identities-d7c52eed-e45c-4483-af3b-4aaa5782bff7" # replace with your project ID
export ORY_SLUG="upbeat-lalande-zu8omm6wwp" # replace with your Ory slug

# List identities via Search API
curl -H "Authorization: Bearer $ORY_API_KEY" \
"https://$ORY_SLUG.projects.oryapis.com/admin/preview/search/v0beta1/collections/$COLLECTION/documents/search?q=*"

# Search for "foo" in the email trait
curl -H "Authorization: Bearer $ORY_API_KEY" \
"https://$ORY_SLUG.projects.oryapis.com/admin/preview/search/v0beta1/collections/$COLLECTION/documents/search?q=foo&query_by=traits.email"

Data model

The collection identities-{your-project-id} contains one document per identity. Each document contains the following fields:

{
"id": "d52d5bdb-74b4-4aa0-b706-d1e9c853bd81", // the identity ID
"organization_id": "org-id-123", // optional, facet
"external_id": "external-id-123", // optional
"created_at": 1725031437, // UNIX timestamp, facet
"updated_at": 1758115258, // UNIX timestamp, facet
"state": "active", // "inactive", "deleted", facet
"schema_id": "preset://email", // identity schema ID, facet
"available_aal": "aal1", // "aal2" etc, facet
"metadata_admin": {
"role": "user" // custom admin metadata, indexed, search via `query_by=metadata_admin.role`
},
"metadata_public": {
"foo": "bar" // custom public metadata, indexed, search via `query_by=metadata_public.foo`
},
"traits": {
"email": "wgiho@agpaa.com" // traits based on identity schema, indexed, search via `query_by=traits.email`
}
}
tip

To avoid timing out search requests, specify the exact fields you want to search in using the query_by parameter. For example, to search for identities by email, use query_by=traits.email.

note

Because of technical limitations, non-string data in metadata_admin and metadata_public will be indexed as strings and returned from the Search API as strings.

To retrieve the original JSON data, fetch the full identity using the Get Identity API.

Advanced search example

Please refer to the Typesense documentation for details on how to construct arbitrary search queries. An example:

export ORY_API_KEY="ory_pat_XXXXXXXXXXXXXXXX"
export COLLECTION="identities-d7c52eed-e45c-4483-af3b-4aaa5782bff7" # replace with your project ID
export ORY_SLUG="upbeat-lalande-zu8omm6wwp" # replace with your Ory slug

# list identities which do not have two-factor authentication enabled,
# resolved by the organization to which they belong,
# ordered by creation date (newest first),
# and limited to 20 per page
curl -H "Authorization: Bearer $ORY_API_KEY" \
"https://$ORY_SLUG.projects.oryapis.com/admin/preview/search/v0beta1/collections/$COLLECTION/documents/search" \
--url-query 'q=*' \
--url-query 'filter_by=available_aal:!=aal2' \
--url-query 'facet_by=organization_id' \
--url-query 'sort_by=created_at:desc' \
--url-query 'per_page=20'
tip

Most fields support infix-searching as well, so queries like query_by=@example.com&infix=always&query_by=traits.email are possible.

Search result set limit

The identity search API does not support pagination (unlike the List Identities API) and will return a maximum of 1,000 results per request. If you are frequently hitting this limit, consider refining your search queries to reduce the number of results returned. To paginate through all your identities, use the List Identities API.

Consistency and availability

The search index powering advanced identity search is eventually consistent with the main identity store. This means that there will be a delay between creating, updating, or deleting an identity and the changes being reflected in search results. We try to aim for a delay of less than one second during normal operation, but cannot provide any guarantees. The search index will have to be rebuilt periodically, during which time we cannot service search requests.

We recommend you use the search API for non-time-critical use cases, such as admin UIs or background jobs, where you need to full capability of full-text search, filtering, faceting, and sorting.

Before displaying search results to end-users or otherwise using the search results for business logic, we recommend you always fetch the full identity from the main identity store using the identity ID returned in search results to ensure you have the most up-to-date information.