Preview — pending review
This reference is generated from the platform API contract and is still under review. Operations, fields, and descriptions can change before publication.
Replace the member's editable access rows
Makes the member's rows the caller may edit equal access, in one transaction. Rows the caller cannot
edit (outside its reach, or without authority at their target) are outside the diff and always kept;
a desired row identical to one of them is a no-op. The same normalization as the invite applies
(dropped); the rows taken away are returned in removed. access: [] removes every editable row --
the member stays a member.
Rows are checked at their OWN target exactly as on the invite (POST /tenants/{tenantId}/iam/users):
404 SCOPE_NOT_FOUND; 403 INSUFFICIENT_ROLE_FOR_SCOPE / CANNOT_GRANT_ABOVE_OWN /
TENANT_OWNER_REQUIRED; 422 ROLE_NOT_FOUND / ROLE_NOT_ASSIGNABLE_AT_SCOPE; precedence
404 > 403 > 422 with details.errors[{index, field, code, message}].
409 details.reason: LAST_TENANT_OWNER (the change would leave the tenant without an owner) or
SELF_IAM_MANAGE_REMOVAL (the caller would remove one of its own rows that confers iam: manage).
Every added / removed row is one iam.user.access.grant / iam.user.access.revoke Activity Log record
and re-projects the member's OpenStack roles. The answer is the full matrix after the change.
Step-up: granting an owner-ranked role (built-in owner, or a custom role that
ranks as owner) from a console session whose account has two-factor authentication needs the
factor verified in the last 5 minutes, otherwise 403 MFA_STEP_UP_REQUIRED (verify with POST /auth/step-up, then retry). Other roles, and an owner row the member already holds, are not
affected.
bearerTokenAuthorizationBearer <token>An API token (pc_live_…) or a service-account key (sak_live_…), created in Identity & Access Management and sent as Authorization: Bearer <token>. Requests are rate limited per credential and per tenant: every response carries X-RateLimit-Limit, X-RateLimit-Remaining and X-RateLimit-Reset, and a refused request gets 429 RATE_LIMITED with Retry-After.
tenantId*stringThe tenant id.
userId*stringThe member (its id is its email).
application/json- body
The member's desired editable rows (PUT).
access*array<>items <= 500The matrix after the change.
application/json- response
A member's access matrix in the tenant.
userId*stringtenantId*stringrows*array<>hiddenCount*integerRows at scopes the caller does not reach (not listed, never changed by its writes).
0 <= valuesummary*What a member can reach in the tenant, for list rows. tenant when it holds any tenant row; scoped when it holds subscription/project rows only; none when it holds no row. The counts are the distinct subscriptions / projects named by its explicit rows (computed over every row, including ones the viewer cannot edit).
dropped*array<>Input rows not written because another row already grants them (writes only).
removed*array<>Rows the write removed (writes only).
curl -X PUT "https://example.com/tenants/string/iam/users/string/access" \ -H "Content-Type: application/json" \ -d '{ "access": [ { "scopeKind": "tenant", "scopeId": "string", "role": "string" } ] }'{ "userId": "string", "tenantId": "string", "rows": [ { "assignmentId": "string", "scopeKind": "tenant", "scopeId": "string", "scopeName": "string", "subscriptionId": "string", "role": "string", "roleName": "string", "grantedBy": "string", "createdAt": "2019-08-24T14:15:22Z", "editable": true } ], "hiddenCount": 0, "summary": { "kind": "tenant", "subscriptions": 0, "projects": 0 }, "dropped": [ { "index": 0, "scopeKind": "tenant", "scopeId": "string", "role": "string", "reason": "DUPLICATE", "coveredBy": { "scopeKind": "tenant", "scopeId": "string" } } ], "removed": [ { "assignmentId": "string", "scopeKind": "tenant", "scopeId": "string", "scopeName": "string", "subscriptionId": "string", "role": "string", "roleName": "string", "grantedBy": "string", "createdAt": "2019-08-24T14:15:22Z", "editable": true } ]}