Move a reseller one level up to distributor, in place. Restricted to owner-level authority: a user of the Owner organization, or a Super Admin. A Super Admin that does not belong to the Owner organization acts within its own scope only — it can promote the resellers its own organization manages, never a peer's and never the organization it belongs to (403 otherwise).
The organization keeps its id and logto_id, so its customers, users,
systems, applications, alert history and Mimir tenant stay attached. Its
custom_data.createdBy moves to the Owner organization, so the
distributor that manages it drops it — and the customers under it — from
its scope, and the alerting config chain stops inheriting that
distributor's layer.
Members get the Distributor organization role in place of Reseller,
so each of them picks up the new level at the next login or token
refresh.
Rejected with 409 when the reseller is suspended (reactivate it first),
when it is not yet synced with Logto, or when the Owner organization
cannot be resolved; with 400 when its VAT already belongs to an active
distributor (VAT is unique per level). Both carry the
validation_error shape with stable message codes — see the
individual responses.
Responses
-
Reseller promoted successfully
-
Validation failed.
data.typeis alwaysvalidation_erroranddata.errors[]carries a stablemessagecode the UI turns into an i18n key:already existsoncustom_data.vatwhen the VAT already belongs to an active distributor (valueis the VAT). -
Unauthorized - invalid or missing token
-
Forbidden - insufficient permissions
-
Resource not found
-
The organization cannot be promoted in its current state. Same
validation_errorshape as the 400, on keypromote, with stablemessagecodes:organization_is_suspended(reactivate it first),organization_not_synced(no Logto organization yet),owner_organization_not_found(no Owner organization to attach it to).
curl \
--request PATCH 'https://api.your-domain.com/api/resellers/{id}/promote' \
--header "Authorization: Bearer $ACCESS_TOKEN"
{
"code": 200,
"message": "reseller promoted to distributor successfully",
"data": {
"distributor": {
"id": "4405ffd0-0aca-44ef-bae2-c8545bce94f4",
"logto_id": "akkbs6x2wo82",
"name": "ACME Distribution SpA",
"description": "Main distributor for Italian and Swiss markets",
"custom_data": {
"email": "contact@acme-distribution.com",
"contactPerson": "John Smith",
"region": "Italy"
},
"suspended_at": "2026-05-04T09:42:00Z",
"suspended_by_org_id": "string",
"rebranding_enabled": false,
"rebranding_org_id": "string",
"created_by": {
"user_id": "aa15fcvgzw1y",
"username": "owner",
"name": "Nethesis Owner",
"email": "owner@nethesis.it",
"organization_id": "2wl3iixbc8ua",
"organization_name": "Owner",
"on_behalf_of": true
}
},
"detached_from_organization_id": "5j8k2m4n6p8q",
"parent_organization_id": "aa15fcvgzw1y",
"customers_count": 12,
"users_count": 3,
"systems_count": 4,
"members_role_switched": 3,
"warnings": [
"string"
]
}
}
{
"code": 400,
"message": "validation failed",
"data": {
"type": "validation_error",
"errors": [
{
"key": "custom_data.vat",
"message": "already exists",
"value": "12345678901"
}
]
}
}
{
"code": 401,
"message": "invalid token",
"data": {}
}
{
"code": 403,
"message": "insufficient permissions",
"data": {}
}
{
"code": 400,
"message": "validation failed",
"data": {
"type": "validation_error",
"errors": [
{
"key": "username",
"message": "required",
"value": "string"
}
]
}
}
{
"code": 409,
"message": "validation failed",
"data": {
"type": "validation_error",
"errors": [
{
"key": "promote",
"message": "organization_is_suspended"
}
]
}
}