Skip to content

Partner provisioning

Provisioning lets a partner application create a MyCLM organization for each of its customers, then keep its structure and users in sync, using your own identifiers (externalId).

  1. Create the organization with its first entity and its owner.

    Terminal window
    curl -s -X POST "$MLT_API_URL/v1/provisioning/orgs" \
    -H "Authorization: Bearer $MLT_TOKEN" -H "Content-Type: application/json" \
    -d '{
    "name": "Cabinet Bernard Immobilier",
    "externalId": "agency-8841",
    "firstEntity": { "name": "Agence Lyon 6e", "externalId": "agency-8841-lyon6" },
    "owner": {
    "email": "claire.bernard@cabinet-bernard.fr", "firstName": "Claire", "lastName": "Bernard",
    "locale": "fr", "externalId": "user-1207", "sendInvitation": false
    }
    }'

    The application automatically gets access to the organizations it creates (a provisioned grant with the admin role, limited to its scopes). With sendInvitation: false, the owner account is created without invitation email: use it with SSO or with your own onboarding email.

  2. Add teams (groups) under the entity, referenced by your ids:

    POST /v1/provisioning/orgs/{orgId}/nodes
    { "parentExternalId": "agency-8841-lyon6", "type": "group", "name": "Gestion locative", "externalId": "team-42" }

    Entities are created directly under the organization ("type": "entity", no parent needed); groups under parentId or parentExternalId.

  3. Add users to a node with a role (system role key admin, manager, member, viewer, or a role id):

    POST /v1/provisioning/orgs/{orgId}/members
    {
    "email": "paul.martin@cabinet-bernard.fr", "firstName": "Paul", "lastName": "Martin", "locale": "fr",
    "externalId": "user-1208", "nodeExternalId": "team-42", "role": "member", "sendInvitation": true
    }

    The account is created when needed. Applications cannot grant the owner role (403 role_escalation).

Every provisioning POST that carries an externalId is idempotent: when a resource with the same externalId already exists, it is returned with 200 and created: false instead of 201. Retry freely after a timeout, and run your sync jobs as “ensure” operations.

An externalId used by another resource of the same kind answers 409 external_id_taken.

Need Call
Find a user by your id GET /v1/provisioning/users?externalId=user-1208: the user and their memberships in your organizations.
Change role or node PATCH /v1/provisioning/memberships/{id} with { "role": "manager" } or { "nodeId": "…" }.
Remove from a node DELETE /v1/provisioning/memberships/{id} (the last owner cannot be removed: 409 last_owner).
List your organizations GET /v1/provisioning/orgs, optionally ?externalId=agency-8841.
Resolve a node by your id GET /v1/provisioning/orgs/{orgId}/nodes?externalId=team-42.

Roles are bounded by the role of your application in the organization: never owner (by key or by id), never above the grant role, and memberships above it cannot be changed nor removed (403 role_escalation).

Then work for these users with delegated OAuth once they authorized your application, and receive the events of their organizations through the webhooks of your application.

Every provisioning write is recorded in the audit log of the organization, attributed to your application.