Querying multiple accounts via JMAP by their name

Your question

I tried the following JMAP request:

{
   "methodcalls": [
      ["x:Account/query", {
         "filter": {
            "name": ["groupA", "groupB", "groupC"],
            "domainId": "b"
         }
      }, "b"],
      ["x:Account/get", {
          "#ids" => {
             "name": "x:Account/query",
             "path": "/ids",
             "resultOf": "b"
          }
       }, "c"]
   ],
   "using": ["urn:ietf:params:jmap:core", "urn:stalwart:jmap"]
}

But I get the following error:

{
   "methodResponses":[
      ["error",{
         "type":"unsupportedFilter",
         "description":"Filter on property name is not supported or invalid"
      },"b"],
      ["error",{
         "type":"invalidResultReference",
         "description":"Result reference to b#x:Account\/query not found."
      },"c"]
   ],
   "sessionState":"2e8ccdd2"
}

Do I really have to send N requests to get the account-data for N account-names?
Or is just the syntax to query for multiple names wrong?

Ralf

The source code makes the situation clear. Here is what is happening and what you can do:

The name filter in x:Account/query accepts a single string value, not an array. Passing an array causes the “unsupported filter” error. The filter performs a lookup via account_id_from_email, which is a single-value operation per condition.

To match multiple names in one request, use the RFC 8620 AnyOf (OR) combinator with one name condition per account. The docs confirm that filter conditions are combinable with AnyOf/AllOf/Not:

{
  "methodCalls": [
    ["x:Account/query", {
      "filter": {
        "operator": "OR",
        "conditions": [
          { "name": "groupA" },
          { "name": "groupB" },
          { "name": "groupC" }
        ]
      }
    }, "b"],
    ["x:Account/get", {
      "#ids": {
        "name": "x:Account/query",
        "path": "/ids",
        "resultOf": "b"
      }
    }, "c"]
  ],
  "using": ["urn:ietf:params:jmap:core", "urn:stalwart:jmap"]
}

This lets you resolve all three accounts in a single request without N round-trips. The domainId filter can be added as an additional AllOf condition around the OR block if you need to scope by domain simultaneously.

For reference, the supported filter conditions for x:Account/query are documented at: https://docs.stalw.art/docs/ref/object/account#xaccountquery

This is an automated reply from the Stalwart Help Bot. Other community members may follow up if this answer is incomplete or wrong.

The docu url is NOT reachable :frowning:

I tried now the following JMAP request:

{
  "using" : [ "urn:ietf:params:jmap:core", "urn:stalwart:jmap" ],
  "methodCalls" : [ [ "x:Account/query", {
    "filter" : {
      "operator" : "AND",
      "conditions" : [ {
        "operator" : "OR",
        "conditions" : [ {
          "name" : "nameA"
        }, {
          "name" : "nameB"
        }, {
          "name" : "nameC"
        } ]
      }, {
        "domainId" : "b"
      } ]
    }
  }, "b" ], [ "x:Account/get", {
    "#ids" : {
      "name" : "x:Account/query",
      "path" : "/ids",
      "resultOf" : "b"
    }
  }, "c" ] ]
}

But still got an error:

{
  "methodResponses" : [ [ "error", {
    "type" : "unsupportedFilter",
    "description" : "Only AND is supported in filters"
  }, "b" ], 
  [ "error", {
    "type" : "invalidResultReference",
    "description" : "Result reference to b#x:Account/query not found."
  }, "c" ] ],
  "sessionState" : "2e8ccdd2"
}

Sorry :wink:

Ralf

I thought I try exactly was the bot responded with:

{
    "using": [
        "urn:ietf:params:jmap:core",
        "urn:stalwart:jmap"
    ],
    "methodCalls": [
        [
            "x:Account/query",
            {
                "filter": {
                    "operator": "OR",
                    "conditions": [
                        {
                            "name": "nameA"
                        },
                        {
                            "name": "nameB"
                        },
                        {
                            "name": "nameC"
                        }
                    ]
                }
            },
            "b"
        ],
        [
            "x:Account/get",
            {
                "#ids": {
                    "name": "x:Account/query",
                    "path": "/ids",
                    "resultOf": "b"
                }
            },
            "c"
        ]
    ]
}

But that’s also not working / gives an error:

{
  "methodResponses" : [ [ "error", {
    "type" : "unsupportedFilter",
    "description" : "Only AND is supported in filters"
  }, "b" ], 
  [ "error", {
    "type" : "invalidResultReference",
    "description" : "Result reference to b#x:Account/query not found."
  }, "c" ] ],
  "sessionState" : "2e8ccdd2"
}

The correct link to the documentation including supported filters is at Account | Stalwart. Registry queries are limited to AND queries only at the moment, so that is the reason why your query is failing.

Any plans to add the documented anyOf / OR syntax in the forseable future?

So if I need to get the accountId of N accounts by their name, I need to either send N queries (in one JMAP call) or one for all accounts of a domain with potentially thousand accounts listed with all their data?

Ralf

You can try using Principal/query which supports OR. Make sure to use an account that has permissions to query principals and to enable the global option to allow principal queries.