BetterIAM
Server API

bindings

Bindings give a role to a person, service account, or group, and control when that role actually applies.

Bindings give a role to a person, service account, or group, and control when that role actually applies. A role grants nothing until it is bound: a binding links one role to one subject, and the subject holds the role for as long as the binding says. A binding can be standing (always on), temporary, future-dated, limited to recurring hours, or eligible, which means the subject may take the role just in time, for a bounded period, with a reason, MFA, or a second person's approval. This group creates and changes bindings, runs that activation and approval flow, and answers "who holds what".

Why a binding needs grant authority

Every binding is created under a grant authority: the delegated right to hand out access, with a ceiling on what it may ever grant. Pass authorityId to pick one of your own authorities; otherwise the server uses your root-issued authority (root administrators) or your first active delegated authority. A caller with no active authority gets GRANT_AUTHORITY_REQUIRED. The binding stores the authority's id, and that matters in three ways:

  • Ceiling. Whatever the role says, the binding grants no more than the ceilings of its authority chain allow. They are applied as boundaries every time a request is evaluated.
  • Revocation. When the authority, or any authority above it, is revoked, the binding grants nothing from the next request on.
  • Ownership. Only the holder of that authority, or root, may update or delete the binding or revoke activations of it. A junior administrator cannot undo a senior administrator's grants.

The permission and the authority answer different questions. iam:bindings:create on iam/{roleId} decides which roles you may bind; the authority caps what those bindings can reach.

When a binding applies

A binding without dates or rules is standing: it applies until someone removes it. Four options narrow it without changing the role:

OptionEffect
expiresAtEpoch milliseconds, in the future and at most ten years ahead. The binding stops granting at that instant, is left out of listings unless you pass includeExpired: true, and is deleted with its activations by the purge worker (purgeDeleted).
startsAtEpoch milliseconds, not in the past and at most ten years ahead, before expiresAt. The binding is listed with its start but grants nothing until then. Separation-of-duties rules already count it.
window{ from, to, timeZone, days? }: HH:MM times in an IANA time zone, and weekdays 0 (Sunday) to 6 (every day by default). Outside the window the binding grants nothing. A window whose end is not after its start wraps past midnight and counts as the day it starts on.
eligibleThe binding grants nothing until its subject activates it, for a bounded time.

A group binding reaches every live member of the group, so membership changes grant and remove the role too. See temporary access for dates and windows.

Just-in-time activation

An eligible binding records that its subject may hold a role. The subject activates it with activate when they need the role, and it lapses on its own. That keeps administrator and production roles out of everyday sessions while every elevation leaves a record with a reason. The full walkthrough is in just-in-time elevation.

Each eligible binding carries its activation rules:

SettingEffect
maxActivationMsThe longest activation, from one minute to seven days. Defaults to one hour.
requireJustificationThe activation must state a reason (at most 2048 characters). It is stored on the activation and in the audit trail.
requireMfaOnly a session that completed MFA may activate.
requireApprovalActivation becomes a request that an approver grants or denies.
approverGroupIdOnly live members of this group (or root) may decide, and they are emailed each request.
managerApprovalThe requester's manager (managerId) may decide as well, and is emailed each request.

Passing any of these for a binding that is not eligible fails with INVALID_INPUT; explicit false flags are accepted, so forms can send every checkbox. The tenant's access policy tightens every eligible binding at once: a rule applies when either the binding or the policy sets it, the maximum length is the smaller of the two, and the policy's approvalLifetimeMs (one day by default) is how long a request waits for a decision.

There is one activation record per binding and person. It starts active (or pending when approval is required), and it ends when it reaches expiresAt, when its holder calls deactivate, when an administrator calls revokeActivation, or when the person leaves the group, the binding or role is deleted, or eligibility is turned off. An activation belongs to the person, not the session: signing out does not end it. An access window on the binding still applies while it is active.

Who may elevate and who may approve are ordinary permissions: iam:bindings:activate and iam:bindings:approve on iam/{roleId}. The usual setup is a Member role holding iam:bindings:activate, bound to a group everyone belongs to, and an Approver role bound to the approver group.

Methods12
Serveriam.api.bindings
Clientclient.bindings
HTTPPOST /api/iam/bindings/*
MethodWhat it doesAccess
activateActivates an eligible binding for yourself so you hold its role for a limited time, or records an approval request when the binding requires one.Credential
approveActivationGrants a pending activation request, so the requester holds the role from now until the approved duration ends.Credential
createGives a role to a person, service account, or group under your grant authority, optionally temporary, future-dated, limited to a recurring window, or eligible for just-in-time activation.Credential
deactivateEnds your own activation early, or withdraws your own pending request.Credential
deleteRemoves a binding and every activation of it, so its subject stops holding the role at the next request.Credential
denyActivationRefuses a pending activation request, optionally with a note for the requester.Credential
listLists the tenant's bindings, filtered by role, subject, eligibility, or upcoming expiry.Credential
listActivationsLists activations and activation requests, newest first, filtered by binding, person, role, or status.Credential
listApprovalsLists the pending activation requests you may decide on, oldest first, with the role and the requester.Credential
listMineLists your own bindings, direct and through groups, with any live activation or waiting request, so you can see what you may elevate to.Credential
revokeActivationEnds someone else's activation or pending request immediately, for incident response.Credential
updateChanges a binding's start, expiry, access window, or eligibility settings in place.Credential

activate

Activates an eligible binding for yourself so you hold its role for a limited time, or records an approval request when the binding requires one.

POST/api/iam/bindings/activate
client.bindings.activate()Credential

Used inJust-in-time elevation,Access lifecycle

  • Permission: iam:bindings:activate on the role (iam/{roleId}), from your own ordinary session of the tenant. The binding must apply to you, directly or through a group you are a live member of.
  • Audited as: iam:bindings:activate, plus binding:activate (with activationId, roleId, expiresAt, and the justification) or, when approval is required, binding:activation-requested.
  • Errors: INVALID_TRANSITION when the binding is not eligible, has not started, or has expired, or when it requires approval from named approvers and none of them is active (an empty approver group and no active manager); ACCESS_DENIED when the binding does not apply to you; INVALID_INPUT from an assumed-role session or a session of another tenant, without a required justification, or for a durationMs outside one minute to the effective maximum; MFA_REQUIRED when MFA is required and your session did not complete it; IMPERSONATION_RESTRICTED from a "view as" session; CONFLICT while you already hold a live activation or a waiting request for this binding; INVARIANT_VIOLATION.

durationMs defaults to the effective maximum: the binding's maxActivationMs, capped by the tenant's access policy. Without approval, the result has status: 'active' and active: true, and the role applies from the next request until expiresAt. With approval, the result has status: 'pending'; it lapses after the tenant's approvalLifetimeMs (24 hours by default) unless someone decides. When the deployment sends email, the approver group's live members and, with managerApproval, your manager receive an activation-request. An earlier activation that ended or was denied is replaced, so you can ask again after a refusal.

const activation = await iam.api.bindings.activate(credential, {
  tenantId,
  bindingId,
  durationMs: 30 * 60 * 1000,
  justification: 'INC-4211: restart the payments worker',
});
if (activation.status === 'pending') {
  // Waiting for an approver; bindings.listMine shows it as pendingActivation.
}
Input

Prop

Type

Returns

Prop

Type

Example HTTP request

Only the required fields are shown; replace each <placeholder>. The response is { "data": … } on success or { "error": { "code", "message" } }.

curl -X POST "$IAM_URL/api/iam/bindings/activate" \
  -H "Authorization: Bearer $BETTER_IAM_TOKEN" \
  -H "Content-Type: application/json" \
  -H "X-Better-IAM: 1" \
  -d '{
  "tenantId": "<tenantId>",
  "bindingId": "<bindingId>"
}'
Signature
iam.api.bindings.activate(
  credential: CredentialInput,
  input: {
    tenantId: string;
    bindingId: string;
    durationMs?: number;
    justification?: string;
  },
): Promise<{
  status: 'active' | 'pending' | 'denied';
  active: boolean;
  bindingId: string;
  identityId: string;
  roleId: string;
  activatedAt: number;
  expiresAt: number;
  justification?: string;
  sessionId: string;
  requestedDurationMs?: number;
  decidedBy?: string;
  decidedAt?: number;
  note?: string;
  id: string;
  tenantId: string;
}>

approveActivation

Grants a pending activation request, so the requester holds the role from now until the approved duration ends.

POST/api/iam/bindings/approveActivation
client.bindings.approveActivation()Credential

Used inJust-in-time elevation,Access lifecycle

  • Permission: iam:bindings:approve on the role (iam/{roleId}). When the binding names approvers, you must also be a live member of its approver group, the requester's manager (with managerApproval), or root.
  • Audited as: iam:bindings:approve, plus binding:activation-approved with the new expiresAt and your note.
  • Errors: INVALID_TRANSITION (409) when the request is no longer waiting (decided, withdrawn, or lapsed) or its binding is no longer eligible and live; INVALID_INPUT when you decide your own request, for a durationMs outside one minute to the effective maximum, or for a note over 2048 characters; ACCESS_DENIED when you are not one of the designated approvers; IMPERSONATION_RESTRICTED from a "view as" session; NOT_FOUND; INVARIANT_VIOLATION.

Without durationMs, the requester gets the duration they asked for, capped at the binding's effective maximum as it stands now (the tenant policy may have tightened since the request). Your durationMs replaces the requested one, for example to grant a shorter window than asked. The activation starts when you approve, not when it was requested. The requester is emailed activation-decided when the deployment sends email. Because nobody decides their own request and an impersonating administrator cannot decide in someone's name, approval gives you two-person control.

await iam.api.bindings.approveActivation(credential, {
  tenantId,
  activationId,
  durationMs: 45 * 60 * 1000,
  note: 'Approved for the change window',
});
Input

Prop

Type

Returns

Prop

Type

Example HTTP request

Only the required fields are shown; replace each <placeholder>. The response is { "data": … } on success or { "error": { "code", "message" } }.

curl -X POST "$IAM_URL/api/iam/bindings/approveActivation" \
  -H "Authorization: Bearer $BETTER_IAM_TOKEN" \
  -H "Content-Type: application/json" \
  -H "X-Better-IAM: 1" \
  -d '{
  "tenantId": "<tenantId>",
  "activationId": "<activationId>"
}'
Signature
iam.api.bindings.approveActivation(
  credential: CredentialInput,
  input: { tenantId: string; activationId: string; note?: string; durationMs?: number },
): Promise<{
  status: 'active' | 'pending' | 'denied';
  active: boolean;
  bindingId: string;
  identityId: string;
  roleId: string;
  activatedAt: number;
  expiresAt: number;
  justification?: string;
  sessionId: string;
  requestedDurationMs?: number;
  decidedBy?: string;
  decidedAt?: number;
  note?: string;
  id: string;
  tenantId: string;
}>

create

Gives a role to a person, service account, or group under your grant authority, optionally temporary, future-dated, limited to a recurring window, or eligible for just-in-time activation.

POST/api/iam/bindings/create
client.bindings.create()Credential

Used inTeams and departments,Roles and bindings,Temporary access,Just-in-time elevation,Privileged access,Access lifecycleand 2 more

  • Permission: iam:bindings:create on the role (iam/{roleId}), plus an active grant authority.
  • Audited as: iam:bindings:create.
  • Errors: PROTECTED_RESOURCE for the protected Owner role; NOT_FOUND when the role, group, approver group, or identity is not in this tenant, or the identity is deleted; GRANT_AUTHORITY_REQUIRED when you hold no active grant authority; ACCESS_DENIED when authorityId names an authority that is not yours or is revoked; INVALID_INPUT for an invalid subject type, date, or window, a startsAt that is not before expiresAt, or activation settings on a binding that is not eligible; CONFLICT when the subject already has a binding of this role under the same authority; SOD_CONFLICT when the binding would give someone a combination of roles a separation-of-duties rule forbids; INVARIANT_VIOLATION when it would newly break an enforced access invariant.

Bind roles to groups where you can: people then gain and lose the role as they join and leave, without anyone editing bindings. The Owner role is never bound this way; ownership changes go through identities.setOwner. An expired binding that the purge worker has not removed yet still counts for CONFLICT; extend it with update instead of creating a new one.

// A contractor gets support access on weekdays, starting next week, for 90 days.
const startsAt = Date.now() + 7 * 86_400_000;
await iam.api.bindings.create(credential, {
  tenantId,
  roleId: support.id,
  subjectType: 'identity',
  subjectId: contractor.id,
  startsAt,
  expiresAt: startsAt + 90 * 86_400_000,
  window: { from: '09:00', to: '17:00', timeZone: 'Europe/Berlin', days: [1, 2, 3, 4, 5] },
});

// The on-call group may take the incident-responder role for up to two hours, with a reason and MFA.
await iam.api.bindings.create(credential, {
  tenantId,
  roleId: responder.id,
  subjectType: 'group',
  subjectId: onCall.id,
  eligible: true,
  maxActivationMs: 2 * 60 * 60 * 1000,
  requireJustification: true,
  requireMfa: true,
});
Input

A BindingInput object:

Prop

Type

Returns

A Binding object:

Prop

Type

Example HTTP request

Only the required fields are shown; replace each <placeholder>. The response is { "data": … } on success or { "error": { "code", "message" } }.

curl -X POST "$IAM_URL/api/iam/bindings/create" \
  -H "Authorization: Bearer $BETTER_IAM_TOKEN" \
  -H "Content-Type: application/json" \
  -H "X-Better-IAM: 1" \
  -d '{
  "tenantId": "<tenantId>",
  "roleId": "<roleId>",
  "subjectType": "identity",
  "subjectId": "<subjectId>"
}'
Signature
iam.api.bindings.create(
  credential: CredentialInput,
  input: BindingInput,
): Promise<Binding>

deactivate

Ends your own activation early, or withdraws your own pending request.

POST/api/iam/bindings/deactivate
client.bindings.deactivate()Credential

Used inJust-in-time elevation,Access lifecycle

  • Permission: iam:bindings:activate on the role (iam/{roleId}); only the person the activation belongs to.
  • Audited as: iam:bindings:activate, plus binding:deactivate (with cancelled: true for a withdrawn request).
  • Errors: ACCESS_DENIED when the activation belongs to someone else (administrators use revokeActivation); NOT_FOUND; INVARIANT_VIOLATION.

Step down when the work is done early: the role stops applying at the next request. The record is deleted, so you can activate again later.

Input

Prop

Type

Returns

Prop

Type

Example HTTP request

Only the required fields are shown; replace each <placeholder>. The response is { "data": … } on success or { "error": { "code", "message" } }.

curl -X POST "$IAM_URL/api/iam/bindings/deactivate" \
  -H "Authorization: Bearer $BETTER_IAM_TOKEN" \
  -H "Content-Type: application/json" \
  -H "X-Better-IAM: 1" \
  -d '{
  "tenantId": "<tenantId>",
  "activationId": "<activationId>"
}'
Signature
iam.api.bindings.deactivate(
  credential: CredentialInput,
  input: { tenantId: string; activationId: string },
): Promise<{ deactivated: boolean }>

delete

Removes a binding and every activation of it, so its subject stops holding the role at the next request.

POST/api/iam/bindings/delete
client.bindings.delete()Credential
  • Permission: iam:bindings:delete on the binding (iam/{bindingId}), and the binding's own grant authority (or root).
  • Audited as: iam:bindings:delete.
  • Errors: ACCESS_DENIED when another administrator's authority issued the binding; PROTECTED_RESOURCE for an Owner binding; NOT_FOUND when the binding is not in this tenant; INVARIANT_VIOLATION when removing it would break an enforced invariant that expects someone to keep access.

To take a group's role away from one person, remove them from the group instead; deleting the group binding removes the role from every member.

Input

Prop

Type

Returns

Prop

Type

Example HTTP request

Only the required fields are shown; replace each <placeholder>. The response is { "data": … } on success or { "error": { "code", "message" } }.

curl -X POST "$IAM_URL/api/iam/bindings/delete" \
  -H "Authorization: Bearer $BETTER_IAM_TOKEN" \
  -H "Content-Type: application/json" \
  -H "X-Better-IAM: 1" \
  -d '{
  "tenantId": "<tenantId>",
  "bindingId": "<bindingId>"
}'
Signature
iam.api.bindings.delete(
  credential: CredentialInput,
  input: { tenantId: string; bindingId: string },
): Promise<{ deleted: boolean }>

denyActivation

Refuses a pending activation request, optionally with a note for the requester.

POST/api/iam/bindings/denyActivation
client.bindings.denyActivation()Credential
  • Permission: iam:bindings:approve on the role (iam/{roleId}), and designated-approver status when the binding names approvers.
  • Audited as: iam:bindings:approve, plus binding:activation-denied with your note.
  • Errors: INVALID_TRANSITION (409) when the request is no longer waiting or its binding is no longer eligible and live; INVALID_INPUT when you decide your own request or the note is over 2048 characters; ACCESS_DENIED when you are not a designated approver; IMPERSONATION_RESTRICTED; NOT_FOUND.

The request becomes status: 'denied' and grants nothing. It stays visible through listActivations({ status: 'denied' }) until the purge worker removes it. The requester is emailed activation-decided with your note when the deployment sends email, and may ask again with activate.

Input

Prop

Type

Returns

Prop

Type

Example HTTP request

Only the required fields are shown; replace each <placeholder>. The response is { "data": … } on success or { "error": { "code", "message" } }.

curl -X POST "$IAM_URL/api/iam/bindings/denyActivation" \
  -H "Authorization: Bearer $BETTER_IAM_TOKEN" \
  -H "Content-Type: application/json" \
  -H "X-Better-IAM: 1" \
  -d '{
  "tenantId": "<tenantId>",
  "activationId": "<activationId>"
}'
Signature
iam.api.bindings.denyActivation(
  credential: CredentialInput,
  input: { tenantId: string; activationId: string; note?: string },
): Promise<{
  status: 'active' | 'pending' | 'denied';
  active: boolean;
  bindingId: string;
  identityId: string;
  roleId: string;
  activatedAt: number;
  expiresAt: number;
  justification?: string;
  sessionId: string;
  requestedDurationMs?: number;
  decidedBy?: string;
  decidedAt?: number;
  note?: string;
  id: string;
  tenantId: string;
}>

list

Lists the tenant's bindings, filtered by role, subject, eligibility, or upcoming expiry.

POST/api/iam/bindings/list
client.bindings.list()Credential

Used inJust-in-time elevation

  • Permission: iam:bindings:read on the role (iam/{roleId}) when you filter by roleId, otherwise on the subject (iam/{subjectId}) when you filter by subjectId, otherwise on the tenant.
  • Audited as: iam:bindings:read.
  • Errors: INVALID_INPUT for an unknown subjectType, a non-boolean eligible, or an invalid expiresBefore.

Expired bindings are left out unless you pass includeExpired: true; future-dated ones are included. eligible: true keeps only eligible bindings and eligible: false only standing ones, which is how you audit standing privileged access. expiresBefore keeps temporary bindings that end at or before that time, for "what ends this month?" reports. Group bindings are returned as stored, not expanded to members: use identities.listBindings for one person's effective roles and roles.listBindings for holders with names.

const endingSoon = await iam.api.bindings.list(credential, {
  tenantId,
  expiresBefore: Date.now() + 14 * 86_400_000,
});
Input

Prop

Type

Returns

An array of Binding.

Prop

Type

Example HTTP request

Only the required fields are shown; replace each <placeholder>. The response is { "data": … } on success or { "error": { "code", "message" } }.

curl -X POST "$IAM_URL/api/iam/bindings/list" \
  -H "Authorization: Bearer $BETTER_IAM_TOKEN" \
  -H "Content-Type: application/json" \
  -H "X-Better-IAM: 1" \
  -d '{
  "tenantId": "<tenantId>"
}'
Signature
iam.api.bindings.list(
  credential: CredentialInput,
  input: {
    tenantId: string;
    roleId?: string;
    subjectType?: 'identity' | 'group';
    subjectId?: string;
    includeExpired?: boolean;
    eligible?: boolean;
    expiresBefore?: number;
  },
): Promise<Binding[]>

listActivations

Lists activations and activation requests, newest first, filtered by binding, person, role, or status.

POST/api/iam/bindings/listActivations
client.bindings.listActivations()Credential

Used inJust-in-time elevation

  • Permission: iam:bindings:read on the first of bindingId, identityId, or roleId you filter by (iam/{id}), otherwise on the tenant.
  • Audited as: iam:bindings:read.
  • Errors: INVALID_INPUT for a status other than pending, active, or denied.

Without status, the result is who is elevated right now: live activations only. status: 'pending' lists open requests, 'active' activations, and 'denied' refusals (all of them, until the purge worker removes them). includeExpired: true adds records that have ended or lapsed but are not yet purged. Each record carries status and active (whether it grants at this moment).

Input

Prop

Type

Returns

An array of object.

Prop

Type

Example HTTP request

Only the required fields are shown; replace each <placeholder>. The response is { "data": … } on success or { "error": { "code", "message" } }.

curl -X POST "$IAM_URL/api/iam/bindings/listActivations" \
  -H "Authorization: Bearer $BETTER_IAM_TOKEN" \
  -H "Content-Type: application/json" \
  -H "X-Better-IAM: 1" \
  -d '{
  "tenantId": "<tenantId>"
}'
Signature
iam.api.bindings.listActivations(
  credential: CredentialInput,
  input: {
    tenantId: string;
    bindingId?: string;
    identityId?: string;
    roleId?: string;
    includeExpired?: boolean;
    status?: 'pending' | 'active' | 'denied';
  },
): Promise<{
  status: 'active' | 'pending' | 'denied';
  active: boolean;
  bindingId: string;
  identityId: string;
  roleId: string;
  activatedAt: number;
  expiresAt: number;
  justification?: string;
  sessionId: string;
  requestedDurationMs?: number;
  decidedBy?: string;
  decidedAt?: number;
  note?: string;
  id: string;
  tenantId: string;
}[]>

listApprovals

Lists the pending activation requests you may decide on, oldest first, with the role and the requester.

POST/api/iam/bindings/listApprovals
client.bindings.listApprovals()Credential

Used inJust-in-time elevation

  • Permission: iam:bindings:approve on the tenant. A request is included only when you also hold iam:bindings:approve on its role and are a designated approver where the binding names any.
  • Audited as: iam:bindings:approve.

It never includes your own requests or requests that have lapsed. Use it to build an approver's inbox; each entry carries role (id and name) and requester (id, name, and email).

Input

Prop

Type

Returns

An array of object & object.

Prop

Type

Example HTTP request

Only the required fields are shown; replace each <placeholder>. The response is { "data": … } on success or { "error": { "code", "message" } }.

curl -X POST "$IAM_URL/api/iam/bindings/listApprovals" \
  -H "Authorization: Bearer $BETTER_IAM_TOKEN" \
  -H "Content-Type: application/json" \
  -H "X-Better-IAM: 1" \
  -d '{
  "tenantId": "<tenantId>"
}'
Signature
iam.api.bindings.listApprovals(
  credential: CredentialInput,
  input: { tenantId: string },
): Promise<({
  status: 'active' | 'pending' | 'denied';
  active: boolean;
  bindingId: string;
  identityId: string;
  roleId: string;
  activatedAt: number;
  expiresAt: number;
  justification?: string;
  sessionId: string;
  requestedDurationMs?: number;
  decidedBy?: string;
  decidedAt?: number;
  note?: string;
  id: string;
  tenantId: string;
} & {
  role?: { id: string; name: string };
  requester?: { id: string; name: string; email?: string };
})[]>

listMine

Lists your own bindings, direct and through groups, with any live activation or waiting request, so you can see what you may elevate to.

POST/api/iam/bindings/listMine
client.bindings.listMine()Credential

Used inJust-in-time elevation

  • Permission: iam:bindings:activate on the tenant, from an ordinary session of the tenant.
  • Audited as: iam:bindings:activate.
  • Errors: INVALID_INPUT from an assumed-role session or a session of another tenant.

It needs no iam:bindings:read, so members see their own access without seeing everyone else's. Each entry is a binding with via ('identity', or { groupId } for a group binding) and its role, plus activation (id, activatedAt, expiresAt) while one is live, pendingActivation (id, requestedAt, expiresAt) while a request waits, and inWindow for bindings with an access window. Standing and eligible bindings are both listed; future-dated ones appear with their startsAt, and expired ones are left out.

Input

Prop

Type

Returns

An array of EffectiveBinding.

Prop

Type

Example HTTP request

Only the required fields are shown; replace each <placeholder>. The response is { "data": … } on success or { "error": { "code", "message" } }.

curl -X POST "$IAM_URL/api/iam/bindings/listMine" \
  -H "Authorization: Bearer $BETTER_IAM_TOKEN" \
  -H "Content-Type: application/json" \
  -H "X-Better-IAM: 1" \
  -d '{
  "tenantId": "<tenantId>"
}'
Signature
iam.api.bindings.listMine(
  credential: CredentialInput,
  input: { tenantId: string },
): Promise<EffectiveBinding[]>

revokeActivation

Ends someone else's activation or pending request immediately, for incident response.

POST/api/iam/bindings/revokeActivation
client.bindings.revokeActivation()Credential
  • Permission: iam:bindings:delete on the binding (iam/{bindingId}), and the binding's own grant authority (or root), like deleting the binding.
  • Audited as: iam:bindings:delete, plus binding:deactivate with revoked: true and the holder's identityId.
  • Errors: ACCESS_DENIED when another administrator's authority issued the binding; NOT_FOUND; INVARIANT_VIOLATION.

Revoking ends the elevation, not the entitlement: the binding stays eligible and the person can activate it again. To stop that, delete the binding or remove the person from its group. Revoking does not end the person's sessions; use identities.revokeSessions for that.

Input

Prop

Type

Returns

Prop

Type

Example HTTP request

Only the required fields are shown; replace each <placeholder>. The response is { "data": … } on success or { "error": { "code", "message" } }.

curl -X POST "$IAM_URL/api/iam/bindings/revokeActivation" \
  -H "Authorization: Bearer $BETTER_IAM_TOKEN" \
  -H "Content-Type: application/json" \
  -H "X-Better-IAM: 1" \
  -d '{
  "tenantId": "<tenantId>",
  "activationId": "<activationId>"
}'
Signature
iam.api.bindings.revokeActivation(
  credential: CredentialInput,
  input: { tenantId: string; activationId: string },
): Promise<{ deactivated: boolean }>

update

Changes a binding's start, expiry, access window, or eligibility settings in place.

POST/api/iam/bindings/update
client.bindings.update()Credential

Used inTemporary access

  • Permission: iam:bindings:create on the role (iam/{roleId}), and the binding's own grant authority (or root).
  • Audited as: iam:bindings:create.
  • Errors: ACCESS_DENIED ("Cannot mutate a higher authority binding") when another administrator's authority issued the binding; PROTECTED_RESOURCE for an Owner binding; INVALID_INPUT when nothing is given to change, or under the same date, window, and setting rules as create; NOT_FOUND; SOD_CONFLICT when extending an already expired binding would create a forbidden combination; INVARIANT_VIOLATION.

Pass null to clear startsAt, expiresAt, window, or approverGroupId. The binding keeps its id and its authority. eligible: false turns an eligible binding into a standing one, drops its activation settings, and ends every activation and pending request of it; eligible: true does the reverse, so the subject stops holding the role until they activate it. Editing a binding that an access package created takes it over: revoking the package no longer removes it.

// Extend a contractor's access by 30 days and drop the business-hours limit.
await iam.api.bindings.update(credential, {
  tenantId,
  bindingId,
  expiresAt: Date.now() + 30 * 86_400_000,
  window: null,
});
Input

Prop

Type

Returns

A Binding object:

Prop

Type

Example HTTP request

Only the required fields are shown; replace each <placeholder>. The response is { "data": … } on success or { "error": { "code", "message" } }.

curl -X POST "$IAM_URL/api/iam/bindings/update" \
  -H "Authorization: Bearer $BETTER_IAM_TOKEN" \
  -H "Content-Type: application/json" \
  -H "X-Better-IAM: 1" \
  -d '{
  "tenantId": "<tenantId>",
  "bindingId": "<bindingId>"
}'
Signature
iam.api.bindings.update(
  credential: CredentialInput,
  input: {
    tenantId: string;
    bindingId: string;
    startsAt?: number | null;
    expiresAt?: number | null;
    window?: AccessWindow | null;
  } & EligibilityInput,
): Promise<Binding>

Was this page helpful?

Better IAM is created by Sean Filimon

Last updated

On this page