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

We recommend using the Typesense SDKs for your preferred language to interact with the advanced identity search API. Pass your Ory Network API key where you would normally pass the Typesense API key, 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.

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.