Your question
How to create/update an account including password, email, aliases, memberships and quota via JMAP?
Thx ![]()
Ralf
Here is a complete breakdown of how to create and update an account via the JMAP API.
x:Account/set / create)Requires the sysAccountCreate permission. POST to /api with urn:stalwart:jmap in the using array:
{
"methodCalls": [
[
"x:Account/set",
{
"create": {
"new1": {
"@type": "User",
"name": "alice",
"domainId": "<Domain id>",
"credentials": [
{
"@type": "Password",
"secret": "supersecret"
}
],
"aliases": [
{ "name": "al", "domainId": "<Domain id>" }
],
"memberGroupIds": ["<group id>"],
"roles": { "@type": "User" },
"permissions": { "@type": "Inherit" },
"quotas": {
"maxDiskQuota": 1073741824
},
"encryptionAtRest": { "@type": "Disabled" }
}
}
},
"c1"
]
],
"using": ["urn:ietf:params:jmap:core", "urn:stalwart:jmap"]
}
Key fields:
| Field | Notes |
|---|---|
@type |
"User" or "Group" |
name |
Email local part (before the @) |
domainId |
ID of the Domain object |
credentials |
Array of Credential objects (see below) |
aliases |
Array of EmailAlias objects: { name, domainId, enabled?, description? } |
memberGroupIds |
Array of Account/Group IDs the user belongs to |
roles |
{ "@type": "User" }, { "@type": "Admin" }, or { "@type": "Custom", "roleIds": [...] } |
permissions |
{ "@type": "Inherit" }, "Merge", or "Replace" with enabledPermissions/disabledPermissions |
quotas |
Map of StorageQuota keys (e.g. maxDiskQuota, maxEmails, maxMailboxes …) to UnsignedInt values |
encryptionAtRest |
{ "@type": "Disabled" } or "Aes128"/"Aes256" with a publicKey |
The credentials field is an array. A password credential looks like:
{
"@type": "Password",
"secret": "plaintextpassword",
"expiresAt": null,
"allowedIps": []
}
x:Account/set / update)Requires sysAccountUpdate. You only need to supply the fields you want to change, keyed by the account’s ID:
{
"methodCalls": [
[
"x:Account/set",
{
"update": {
"<account id>": {
"aliases": [
{ "name": "newalias", "domainId": "<Domain id>" }
],
"memberGroupIds": ["<group id 1>", "<group id 2>"],
"quotas": { "maxDiskQuota": 5368709120 },
"credentials": [
{ "@type": "Password", "secret": "newpassword" }
]
}
}
},
"c1"
]
],
"using": ["urn:ietf:params:jmap:core", "urn:stalwart:jmap"]
}
quotas map)| Key | Meaning |
|---|---|
maxDiskQuota |
Max disk space (bytes) |
maxEmails |
Max emails |
maxMailboxes |
Max mailboxes |
maxCalendars |
Max calendars |
maxContactCards |
Max contact cards |
maxAppPasswords |
Max app passwords |
maxApiKeys |
Max API keys |
| …and more | See full list in the docs |
# Create
stalwart-cli create Account/User \
--field name=alice \
--field 'domainId=<Domain id>' \
--field 'credentials=[{"@type":"Password","secret":"mysecret"}]' \
--field 'memberGroupIds=["<group id>"]' \
--field 'roles={"@type":"User"}' \
--field 'permissions={"@type":"Inherit"}' \
--field 'quotas={"maxDiskQuota":1073741824}' \
--field 'aliases=[{"name":"al","domainId":"<Domain id>"}]' \
--field 'encryptionAtRest={"@type":"Disabled"}'
# Update
stalwart-cli update Account <id> --field description='new description'
Full reference: Account object docs
This is an automated reply from the Stalwart Help Bot. Other community members may follow up if this answer is incomplete or wrong.
That means I have to first search for the domain, to either get it’s ID, or create it (and get the ID).
Same for all memberships of the user, to get the group-IDs.
The domain-ID of a user is determined by the domain of it’s primary email, but he can have aliases from other domains. Can the domain-ID of a user change, when he get an email from an other domain?
Is there such a thing as the primary email of a user, or does the user just has N aliases, with name-part and domain-ID each?
Ralf
Accounts are managed through the Account object in the management API (the same objects the web UI edits), not a plain JMAP Email method. On the user variant the fields you’re asking about are: name (the local part), domainId (the primary domain’s id), credentials (a list, each a Password / AppPassword / ApiKey), aliases (a list, each an EmailAlias of enabled, name, domainId, description), memberGroupIds, roles, permissions, and quotas (a map of storage type to bytes), plus description/locale/timeZone.
On the model questions: the primary email is implicit, name@; it’s server-derived, not a separate alias entry. A user does have N aliases, each its own local part plus domainId, and aliases can be in other domains. Those alias domains do not change the account’s own domainId, which is a single field; changing the primary domain means updating domainId itself. And yes, since the schema stores ids, you’ll resolve the domain and group ids first (query Domain and Account by name) before referencing them, see the querying thread for the mechanics. Docs: stalw.art/docs/ref/object/account.