D0gma_
D0gma_β€’3mo ago

List users with metadata

Hi, is there a way in the API V2 to list all users with their metadata ? The use case is the following : I need to sync my zitadel users periodically with an application, because I can't wait for them to login on this specific app to have an account on it. I can perfectly list all the users with the POST /users endpoint, but I need a very crucial piece of information (the room number of the user for an internet connection providing service), that is in the metadata, and those are not returned in the endpoint (we formerly used keycloak, where the "attributes" were included in the /users endpoints). Am I forced to make one api call by user after listing them to get that info ? Thank you πŸ˜‰
27 Replies
D0gma_
D0gma_OPβ€’3mo ago
Side question : where can I find an up-to-date v2 api documentation for zitadel 4.0.2 (or even v3.3.3 for that matter) ? The currently displayed user creation endpoint .../new returns a "Method Not Allowed" when posted ? Am I missing something ? πŸ˜”
Rajat
Rajatβ€’3mo ago
hey @D0gma_ thanks for your question, there's a PR in works for the same https://github.com/zitadel/zitadel/pull/10415 hope this helps πŸ™‚
Side question : where can I find an up-to-date v2 api documentation for zitadel 4.0.2 (or even v3.3.3 for that matter)
all the APIs listed under V2 works on all zitadel console as long as they're at least V4, you may have to still get around with v1 apis if you are using zitadel cloud as its on v3.3.x I believe. This is the V4 Roadmap for Zitadel it also lists the V2 APIs that you can already use I have said it before πŸ™‚ we are in the middle of transtioning v1->v2 apis hence you might see some apis not being working correctly, but pls lmk if that happens, im here to help πŸ˜„
D0gma_
D0gma_OPβ€’3mo ago
Sounds great thanks ! If everything goes as plan, when can the release be expected ? (Not to rush you in any way, just to have a rough idea πŸ˜…)
Rajat
Rajatβ€’3mo ago
you can check the comments, marco is working on it, he's still implementing another endpoint should not be too long πŸ™‚
D0gma_
D0gma_OPβ€’2mo ago
Ok so that’s strange, I’ll test again tonight (CET) the /new endpoint, and will follow up with a detailed message if I have the same problem Hello @Rajat , quick follow-up, I think I have an issue on Zitadel v4.0.3, following the current documentation for a POST
curl --location 'https://sso.mydomain.fr/v2/users/new' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer thIsIsMyToken' \
--data-raw '{
"organizationId": "333665636326637571",
"username": "minnie-mouse",
"human": {
"profile": {
"givenName": "Minnie",
"familyName": "Mouse",
"nickName": "Mini",
"displayName": "Minnie Mouse",
"preferredLanguage": "en",
"gender": "GENDER_FEMALE"
},
"email": {
"email": "mini@mouse.com"
}
}
}'
curl --location 'https://sso.mydomain.fr/v2/users/new' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer thIsIsMyToken' \
--data-raw '{
"organizationId": "333665636326637571",
"username": "minnie-mouse",
"human": {
"profile": {
"givenName": "Minnie",
"familyName": "Mouse",
"nickName": "Mini",
"displayName": "Minnie Mouse",
"preferredLanguage": "en",
"gender": "GENDER_FEMALE"
},
"email": {
"email": "mini@mouse.com"
}
}
}'
{
"code": 12,
"message": "Method Not Allowed"
}
{
"code": 12,
"message": "Method Not Allowed"
}
The deprecated /human endpoint works tho πŸ‘€
Rajat
Rajatβ€’2mo ago
hey @D0gma_ yes the deprecated /human because we are still transitioning from v1->v2 apis, you will know when it will stop working, more about this on our roadmap
D0gma_
D0gma_OPβ€’2mo ago
Ok so that is normal that the /new endpoint is non-fonctional ?
Rajat
Rajatβ€’2mo ago
hey @D0gma_ no, its not normal, I just got back from my vacation today, I will check up with my team and also test it for myself to see why its not working(you are not doing anything wrong based on past conversations) πŸ™‚
D0gma_
D0gma_OPβ€’2mo ago
Ok that’s clear, thank you πŸ™ƒ
D0gma_
D0gma_OPβ€’2mo ago
Thank you ! What I am not sure reading the doc, is will the metadata be returned in the response ?
Rajat
Rajatβ€’2mo ago
the response should like this but I guess its still broken
Rajat
Rajatβ€’2mo ago
No description
Rajat
Rajatβ€’2mo ago
so it looks like an issue on our end
D0gma_
D0gma_OPβ€’2mo ago
ok thank you, it happens πŸ˜… however, even if it did work, this doesn't seem to contain the metadatas
Rajat
Rajatβ€’2mo ago
hey @D0gma_ can u pls share a screenshot πŸ™‚
D0gma_
D0gma_OPβ€’2mo ago
I get a http 500 error (Zitadel v4.1.3):
{
"query": {
"offset": 0,
"limit": 100,
"asc": true
},
"sortingColumn": "USER_FIELD_NAME_UNSPECIFIED",
"queries": [
{
"metadataKeyFilter": {
"key": "school",
"method": "TEXT_FILTER_METHOD_EQUALS"
}
}
]
}
{
"query": {
"offset": 0,
"limit": 100,
"asc": true
},
"sortingColumn": "USER_FIELD_NAME_UNSPECIFIED",
"queries": [
{
"metadataKeyFilter": {
"key": "school",
"method": "TEXT_FILTER_METHOD_EQUALS"
}
}
]
}
{
"code": 13,
"message": "An internal error occurred (QUERY-AG4gs)",
"details": [
{
"@type": "type.googleapis.com/zitadel.v1.ErrorDetail",
"id": "QUERY-AG4gs",
"message": "An internal error occurred"
}
]
}
{
"code": 13,
"message": "An internal error occurred (QUERY-AG4gs)",
"details": [
{
"@type": "type.googleapis.com/zitadel.v1.ErrorDetail",
"id": "QUERY-AG4gs",
"message": "An internal error occurred"
}
]
}
But beside that, what I meant was "I thought the scope of this feature was also to provide the user metadata in the response of the query, did I misunderstood that ?"
Rajat
Rajatβ€’2mo ago
cc @Federico
fcoppede
fcoppedeβ€’2mo ago
this feature has not been released yet, you can review that here: - https://github.com/zitadel/zitadel/releases - https://github.com/zitadel/zitadel/pull/10415
D0gma_
D0gma_OPβ€’2mo ago
@Rajat Ok nice so in 4.2.0 that works πŸ”₯ , but that doesn't quite solve my initial usecase, because the metadata (queried or not), are not returned in the response. I cannot determine the metadata value of several users whithout doing a call for each, I can only know which user have this metadata key
Rajat
Rajatβ€’5w ago
hey @D0gma_
I cannot determine the metadata value of several users whithout doing a call for each, I can only know which user have this metadata key
pls share your curl call and what did you expect to happen?. Thanks
D0gma_
D0gma_OPβ€’4w ago
Hi, what i mean is when i filter my user search by metadata key, I would suppose I have access to the corresponding metadata value for each user directly. For instance, with this :
curl --location 'https://my-zitadel.fr/v2/users' \
--header 'Content-Type: application/json' \
--header 'Accept: application/json' \
--header 'Authorization: Bearer TOKEN' \
--data '{
"query": {
"offset": 0,
"limit": 100,
"asc": true
},
"sortingColumn": "USER_FIELD_NAME_UNSPECIFIED",
"queries": [
{
"metadataKeyFilter": {
"key": "school",
"method": "TEXT_FILTER_METHOD_EQUALS"
}
}
]
}'
curl --location 'https://my-zitadel.fr/v2/users' \
--header 'Content-Type: application/json' \
--header 'Accept: application/json' \
--header 'Authorization: Bearer TOKEN' \
--data '{
"query": {
"offset": 0,
"limit": 100,
"asc": true
},
"sortingColumn": "USER_FIELD_NAME_UNSPECIFIED",
"queries": [
{
"metadataKeyFilter": {
"key": "school",
"method": "TEXT_FILTER_METHOD_EQUALS"
}
}
]
}'
I'd expect to have a response like this :
{
"details": {
"totalResult": "8",
"timestamp": "2025-09-27T12:39:28.729484Z"
},
"result": [
{
"userId": "333789809954783235",
"details": {
"sequence": "19",
"changeDate": "2025-08-28T21:42:42.814094Z",
"resourceOwner": "333665636326637571",
"creationDate": "2025-08-17T17:03:50.532278Z"
},
"state": "USER_STATE_ACTIVE",
"username": "username",
"loginNames": [
"username"
],
"preferredLoginName": "username",
"human": {
"profile": {
"givenName": "First",
"familyName": "Last",
"nickName": "",
"displayName": "First Last",
"preferredLanguage": "und",
"gender": "GENDER_MALE"
},
"email": {
"email": "example@example.com",
"isVerified": true
},
"phone": {},
"passwordChanged": "2025-08-17T22:19:10.290020Z",
"mfaInitSkipped": "2025-08-17T22:19:43.985007Z",
"metadata": [
{
"creationDate": "2025-01-23T10:34:18.051Z",
"changeDate": "2025-01-23T10:34:18.051Z",
"key": "school",
"value": "VGhpcyBpcyBteSBmaXJzdCB2YWx1ZQ=="
}
]
}
},
...
{
"details": {
"totalResult": "8",
"timestamp": "2025-09-27T12:39:28.729484Z"
},
"result": [
{
"userId": "333789809954783235",
"details": {
"sequence": "19",
"changeDate": "2025-08-28T21:42:42.814094Z",
"resourceOwner": "333665636326637571",
"creationDate": "2025-08-17T17:03:50.532278Z"
},
"state": "USER_STATE_ACTIVE",
"username": "username",
"loginNames": [
"username"
],
"preferredLoginName": "username",
"human": {
"profile": {
"givenName": "First",
"familyName": "Last",
"nickName": "",
"displayName": "First Last",
"preferredLanguage": "und",
"gender": "GENDER_MALE"
},
"email": {
"email": "example@example.com",
"isVerified": true
},
"phone": {},
"passwordChanged": "2025-08-17T22:19:10.290020Z",
"mfaInitSkipped": "2025-08-17T22:19:43.985007Z",
"metadata": [
{
"creationDate": "2025-01-23T10:34:18.051Z",
"changeDate": "2025-01-23T10:34:18.051Z",
"key": "school",
"value": "VGhpcyBpcyBteSBmaXJzdCB2YWx1ZQ=="
}
]
}
},
...
because just knowing which users have the school metadata is pretty useless for me (they pretty much all do), what I am interested in is getting a batch of the metadata value associated to the school key for several users at a time.
Rajat
Rajatβ€’4w ago
ahh okay, so is it like, you want to get all the metadata set for a user based on if one key is matched?. I think that wont be possible, but that would be due to security considerations, please lmk if I am getting it correctly?.
D0gma_
D0gma_OPβ€’4w ago
Well almost that πŸ˜€ not all the metadata set, but the value associated to the matched key, for every user matched at once
Rajat
Rajatβ€’4w ago
ahh then you need to change TEXT_FILTER_METHOD_EQUALS
D0gma_
D0gma_OPβ€’4w ago
How so ?
Rajat
Rajatβ€’4w ago
to TEXT_FILTER_METHOD_CONTAINS probably, check here
No description

Did you find this page helpful?