BetterIAM
Server API

guests

Guests are people from outside an organization, or from another tenant, who work inside it for a limited time.

Guests are people from outside an organization, or from another tenant, who work inside it for a limited time. An organization invites them by email, a sponsor vouches for each one and renews their access, and access ends unless it is renewed. A guest is an ordinary person (kind: 'user') of the host tenant with a server-owned guest marker, so roles, groups, access packages, separation of duties, invariants, certifications, expiry, and offboarding apply to guests unchanged, and policies can single them out with principal.guest, principal.guestSponsorId, and principal.homeTenantId. The repository guide is Guests.

Guests and sponsors

Every guest has a sponsor: an active, unexpired person of the host tenant who is not a guest. invite makes the caller the sponsor unless sponsorId names someone else. The sponsor renews the guest's access with attest without any permission and sees their guests with mine. A guest's access ends at the identity's expiresAt (90 days after redemption by default); from then on every credential of the guest is refused, and everything the invitation granted ends with it. When a sponsor leaves, offboarding with a successor hands their guests over, and otherwise the guests are flagged sponsorMissing until an administrator calls setSponsor.

A guest account's accountStatus is active, expired (the access ended), removed (by remove or offboarding), or converted (by convertToMember).

Cross-tenant access settings

Each tenant has inbound settings (whether it accepts guests, allowed and blocked email domains, and partner organizations admitted or refused over those defaults) and outbound settings (whether people at its verified domains may become guests elsewhere, with partner exceptions). An address whose domain another tenant verified belongs to that tenant: the guest is tenant-sourced (homeTenantId), and both the host's inbound and the home tenant's outbound settings must admit them. Admission is checked when an invitation is sent, sent again, and redeemed, and a refusal is GUEST_NOT_ALLOWED. The settings also hold the default access and review periods and an optional guestBoundary, a policy that caps every guest's decisions in the tenant. See configure.

Who may call what

Administrators hold iam:guests:read, iam:guests:invite, iam:guests:manage, or iam:guests:settings on iam/guests, iam/guests/{identityId}, iam/guests/invitations, iam/guests/invitations/{id}, and iam/guests/settings. setSponsor, remove, convertToMember, and configure also need a recent sign-in. redeem is public, mine needs only a person's own session or API key in the tenant, and a guest's sponsor calls attest without any permission. Guests hold none of these rights over other guests, renew nobody's access, choose no sponsor, and make nobody a member, themselves included.

Methods14
Serveriam.api.guests
Clientclient.guests
HTTPPOST /api/iam/guests/*
MethodWhat it doesAccess
attestRenews a guest's access, together with everything the invitation granted.Credential
configureChanges the tenant's cross-tenant access settings: who may join as a guest, where its people may be guests, the default periods, and the guest boundary.Credential
convertToMemberMakes an active guest an ordinary member of the organization.Credential
getReturns one guest with their sponsor, invitation, renewal, access end, and last sign-in.Credential
getSettingsReturns the tenant's cross-tenant access settings, or the defaults until they are configured.Credential
inviteInvites a person from outside the organization as a guest and emails them a personal invitation.Credential
listLists the tenant's guests by name, with their sponsor, access end, next review, and last sign-in.Credential
listInvitationsLists the tenant's guest invitations, newest first, without their tokens.Credential
mineLists the active guests the caller sponsors, the soonest review first.Credential
redeemRedeems a guest invitation: creates the guest with the invited address and a password, grants what the invitation grants, and signs them in.Public
removeRemoves a guest: disables them and takes away everything they hold, in one transaction.Credential
resendInvitationSends a pending or lapsed guest invitation again with a new token and a new lifetime.Credential
revokeInvitationWithdraws a pending guest invitation, so its token stops working.Credential
setSponsorGives an active guest a new sponsor and clears a missing-sponsor flag.Credential

attest

Renews a guest's access, together with everything the invitation granted.

POST/api/iam/guests/attest
client.guests.attest()Credential

Used inGuests

  • Permission: None for the guest's sponsor in their own session or API key (never while impersonating); anyone else needs iam:guests:manage on iam/guests/{identityId}.
  • Audited as: guest:attest with the new end, the next review, and asSponsor; an administrator's call also as iam:guests:manage.
  • Errors: INVALID_TRANSITION (409) when the guest is disabled or their access ended; ACCESS_DENIED for a guest (their own access included), for a sponsor calling from anything but their own session or API key in the tenant, or for anyone else without the permission; TENANT_UNAVAILABLE for a sponsor's renewal while the tenant or an ancestor is not active; IMPERSONATION_RESTRICTED for a sponsor who is being impersonated; INVALID_INPUT for days outside 1 to 365; NOT_FOUND.

The access then ends days from now (the tenant's accessDays by default), and the next review is due after the tenant's reviewEveryDays, or at the new end if that is sooner. The invitation's bindings, memberships, and package assignments move to the new end, even when an administrator changed the guest's expiresAt in between; grants whose end was changed by hand keep theirs, and a package assignment keeps its end when the package's maximum duration does not allow the new one. A package assignment lengthens only the memberships it created at redemption, so a group the package gained since, or a membership the guest holds another way, keeps its end. Because a renewal moves only what the invitation granted and ends again within a year, it needs no iam:licenses:assign for licensed groups. To bring back a guest whose access ended, extend expiresAt and re-enable them with identities.update and identities.setStatus.

await iam.api.guests.attest(sponsorSession, { tenantId, identityId: ginaId, days: 90 });
Input

Prop

Type

Returns

A GuestView 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/guests/attest" \
  -H "Authorization: Bearer $BETTER_IAM_TOKEN" \
  -H "Content-Type: application/json" \
  -H "X-Better-IAM: 1" \
  -d '{
  "tenantId": "<tenantId>",
  "identityId": "<identityId>"
}'
Signature
iam.api.guests.attest(
  credential: CredentialInput,
  input: { tenantId: string; identityId: string; days?: number },
): Promise<GuestView>

configure

Changes the tenant's cross-tenant access settings: who may join as a guest, where its people may be guests, the default periods, and the guest boundary.

POST/api/iam/guests/configure
client.guests.configure()Credential

Used inGuests

  • Permission: iam:guests:settings on iam/guests/settings, and a recent sign-in.
  • Audited as: iam:guests:settings, plus guest:settings with the changed setting names and the settings after the change (whether a boundary is set, not the document).
  • Errors: INVALID_INPUT for an unknown setting (at the top level or inside inbound or outbound), nothing to change, a flag that is not a boolean, a malformed domain, a domain or partner list of more than 100 entries, a partner entry naming this tenant, an unknown tenant, or a tenant already listed, an accessDays outside 1 to 365, or a reviewEveryDays outside 7 to 365; INVALID_POLICY or INVALID_ACTION for a malformed guestBoundary; RECENT_AUTH_REQUIRED.

Only the fields given change, inside inbound and outbound too, and guestBoundary: null removes the boundary. Domains match themselves and their subdomains and are stored lowercase. On the inbound side a refusing partner entry wins, then a blocked domain, then an admitting partner entry, then allowGuests and allowedDomains. On the outbound side a partner entry for the host decides, else allowGuestInvitations. The other organization's refusal is reported without revealing its settings. The boundary is a ceiling like a tenant boundary: it grants nothing and applies to guests only.

await iam.api.guests.configure(credential, {
  tenantId,
  inbound: { allowedDomains: ['partner.example'], partners: [{ tenantId: globexId, allow: true }] },
  reviewEveryDays: 30,
  guestBoundary: {
    version: 1,
    statements: [{ effect: 'allow', actions: ['documents:read'], resources: ['document/shared-*'] }],
  },
});
Input

A GuestSettingsInput object:

Prop

Type

Returns

A GuestSettingsView 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/guests/configure" \
  -H "Authorization: Bearer $BETTER_IAM_TOKEN" \
  -H "Content-Type: application/json" \
  -H "X-Better-IAM: 1" \
  -d '{
  "tenantId": "<tenantId>"
}'
Signature
iam.api.guests.configure(
  credential: CredentialInput,
  input: GuestSettingsInput,
): Promise<GuestSettingsView>

convertToMember

Makes an active guest an ordinary member of the organization.

POST/api/iam/guests/convertToMember
client.guests.convertToMember()Credential

Used inGuests

  • Permission: iam:guests:manage on iam/guests/{identityId}, and a recent sign-in. With clearExpiry, also iam:licenses:assign when a license product is assigned to a group whose membership would lose its end.
  • Audited as: iam:guests:manage, plus guest:convert with clearExpiry and the previous access end.
  • Errors: INVALID_TRANSITION (409) unless the guest is active, enabled, and within their access; INVALID_INPUT for a clearExpiry that is not a boolean; ACCESS_DENIED for clearExpiry on a licensed group without iam:licenses:assign (audited as a denial); RECENT_AUTH_REQUIRED; NOT_FOUND.

The guest marker goes, so policies see principal.guest: false from the next request (the same session included) and the guest boundary no longer applies. The guest account closes as converted, and birthright rules run again for the new member. The access end stays unless clearExpiry: true removes it together with the end of what the invitation granted. The result is the public identity.

Input

Prop

Type

Returns

A PublicIdentity 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/guests/convertToMember" \
  -H "Authorization: Bearer $BETTER_IAM_TOKEN" \
  -H "Content-Type: application/json" \
  -H "X-Better-IAM: 1" \
  -d '{
  "tenantId": "<tenantId>",
  "identityId": "<identityId>"
}'
Signature
iam.api.guests.convertToMember(
  credential: CredentialInput,
  input: { tenantId: string; identityId: string; clearExpiry?: boolean },
): Promise<PublicIdentity>

get

Returns one guest with their sponsor, invitation, renewal, access end, and last sign-in.

POST/api/iam/guests/get
client.guests.get()Credential

Used inGuests

  • Permission: iam:guests:read on iam/guests/{identityId}.
  • Audited as: iam:guests:read.
  • Errors: NOT_FOUND when the identity is not a guest of this tenant (members and deleted identities included).

A converted guest is still returned, with accountStatus: 'converted'.

Input

Prop

Type

Returns

A GuestView 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/guests/get" \
  -H "Authorization: Bearer $BETTER_IAM_TOKEN" \
  -H "Content-Type: application/json" \
  -H "X-Better-IAM: 1" \
  -d '{
  "tenantId": "<tenantId>",
  "identityId": "<identityId>"
}'
Signature
iam.api.guests.get(
  credential: CredentialInput,
  input: { tenantId: string; identityId: string },
): Promise<GuestView>

getSettings

Returns the tenant's cross-tenant access settings, or the defaults until they are configured.

POST/api/iam/guests/getSettings
client.guests.getSettings()Credential
  • Permission: iam:guests:read on iam/guests/settings.
  • Audited as: iam:guests:read.

configured is false while the tenant uses the defaults: guests accepted from any domain, the tenant's people free to become guests elsewhere, 90 days of access, and a review every 90 days.

Input

Prop

Type

Returns

A GuestSettingsView 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/guests/getSettings" \
  -H "Authorization: Bearer $BETTER_IAM_TOKEN" \
  -H "Content-Type: application/json" \
  -H "X-Better-IAM: 1" \
  -d '{
  "tenantId": "<tenantId>"
}'
Signature
iam.api.guests.getSettings(
  credential: CredentialInput,
  input: { tenantId: string },
): Promise<GuestSettingsView>

invite

Invites a person from outside the organization as a guest and emails them a personal invitation.

POST/api/iam/guests/invite
client.guests.invite()Credential

Used inGuests

  • Permission: iam:guests:invite on iam/guests/invitations, plus, for what the invitation grants, iam:bindings:create on each role, iam:groups:update on each group with the authorities behind the group's bindings, iam:packages:assign on each package with the rights to assign it by hand, and iam:licenses:assign when a license product is assigned to one of the groups or of the packages' groups (checked again at redemption). Naming someone other than yourself as sponsorId also needs iam:guests:manage on iam/guests/invitations.
  • Audited as: iam:guests:invite, plus guest:invite with the address, sponsor, grants, access days, and lapse.
  • Errors: DELIVERY_REQUIRED without an email delivery callback; TENANT_INACTIVE when the tenant is not active; CONFLICT (409) when someone in the tenant has the address or it has a pending invitation; GUEST_NOT_ALLOWED (403) for an address at one of the tenant's own verified domains, or when the inbound or the home organization's outbound settings refuse it; INVALID_SPONSOR when sponsorId is not an active member who is not a guest, or is left out by a caller who cannot sponsor (a root administrator, a service account's key, a delegated session); IMPERSONATION_RESTRICTED; GRANT_AUTHORITY_REQUIRED for roles or groups without a grant authority; PROTECTED_RESOURCE for a protected role; TEAM_MANAGED for a team's backing group; NOT_FOUND for a role, group, or package outside the tenant; ACCESS_DENIED without the rights to grant them, without iam:guests:manage when naming someone else as the sponsor, or from an assumed role (redemption re-checks the inviter's own rights); INVALID_INPUT for a malformed email or one whose domain is not a DNS name (the domain is compared and stored lowercase, in punycode, without a trailing dot), an accessDays outside 1 to 365, an expiresInDays outside 1 to 30, a message over 1000 characters or with line breaks, more than 100 roles, groups, or packages, or the platform tenant.

The email (template guest-invitation) carries a biam_gst_… token that is stored only as a hash and returned nowhere else; point links.guestInvitation in the email templates at the page that calls redeem. The invitation lapses after expiresInDays (14 by default), and the guest's access lasts accessDays from redemption (the tenant's default, 90 unless configured). Roles and groups are granted at redemption under the inviter's grant authority and packages under the inviter's rights, so an invitation never grants more than its inviter could by hand.

const invitation = await iam.api.guests.invite(credential, {
  tenantId,
  email: 'gina@partner.example',
  sponsorId: aliceId,
  message: 'Welcome to the launch project',
  roleIds: [viewerRoleId],
  groupIds: [launchGroupId],
  accessDays: 30,
});
Input

A GuestInviteInput object:

Prop

Type

Returns

A GuestInvitationView 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/guests/invite" \
  -H "Authorization: Bearer $BETTER_IAM_TOKEN" \
  -H "Content-Type: application/json" \
  -H "X-Better-IAM: 1" \
  -d '{
  "tenantId": "<tenantId>",
  "email": "<email>"
}'
Signature
iam.api.guests.invite(
  credential: CredentialInput,
  input: GuestInviteInput,
): Promise<GuestInvitationView>

list

Lists the tenant's guests by name, with their sponsor, access end, next review, and last sign-in.

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

Used inGuests

  • Permission: iam:guests:read on iam/guests.
  • Audited as: iam:guests:read.
  • Errors: INVALID_INPUT for a status other than active, expired, removed, or converted, a limit outside 1 to 1000, an offset outside 0 to 1000000, or an expiringWithinDays outside 0 to 3650.

Filter by sponsorId, by account status (an active guest whose access ended counts as expired), or by expiringWithinDays (access ending at most that many days from now, ended ones included). total counts every match before paging with limit (100 by default) and offset.

Input

Prop

Type

Returns

A GuestPage 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/guests/list" \
  -H "Authorization: Bearer $BETTER_IAM_TOKEN" \
  -H "Content-Type: application/json" \
  -H "X-Better-IAM: 1" \
  -d '{
  "tenantId": "<tenantId>"
}'
Signature
iam.api.guests.list(
  credential: CredentialInput,
  input: {
    tenantId: string;
    sponsorId?: string;
    status?: GuestAccountStatus;
    expiringWithinDays?: number;
    limit?: number;
    offset?: number;
  },
): Promise<GuestPage>

listInvitations

Lists the tenant's guest invitations, newest first, without their tokens.

POST/api/iam/guests/listInvitations
client.guests.listInvitations()Credential

Used inGuests

  • Permission: iam:guests:read on iam/guests/invitations.
  • Audited as: iam:guests:read.
  • Errors: INVALID_INPUT for a status other than pending, redeemed, revoked, or expired.

A pending invitation past its lapse is reported as expired before the sweep job records it. Invitations revoked because their inviter or sponsor was disabled or left carry revokedReason (inviter-inactive or sponsor-inactive). Redeemed ones name the guest in identityId.

Input

Prop

Type

Returns

An array of GuestInvitationView.

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/guests/listInvitations" \
  -H "Authorization: Bearer $BETTER_IAM_TOKEN" \
  -H "Content-Type: application/json" \
  -H "X-Better-IAM: 1" \
  -d '{
  "tenantId": "<tenantId>"
}'
Signature
iam.api.guests.listInvitations(
  credential: CredentialInput,
  input: { tenantId: string; status?: GuestInvitationStatus },
): Promise<GuestInvitationView[]>

mine

Lists the active guests the caller sponsors, the soonest review first.

POST/api/iam/guests/mine
client.guests.mine()Credential

Used inGuests

  • Permission: None beyond a person's own session or API key in the tenant.
  • Audited as: Not audited; it only reads.
  • Errors: ACCESS_DENIED from a role session, session token, delegated session, or a session of another tenant.

It backs a "guests I sponsor" page where sponsors see each guest's review date and access end and renew them with attest. A person who sponsors nobody gets an empty list.

Input

Prop

Type

Returns

An array of GuestView.

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/guests/mine" \
  -H "Authorization: Bearer $BETTER_IAM_TOKEN" \
  -H "Content-Type: application/json" \
  -H "X-Better-IAM: 1" \
  -d '{
  "tenantId": "<tenantId>"
}'
Signature
iam.api.guests.mine(
  credential: CredentialInput,
  input: { tenantId: string },
): Promise<GuestView[]>

redeem

Redeems a guest invitation: creates the guest with the invited address and a password, grants what the invitation grants, and signs them in.

POST/api/iam/guests/redeem
client.guests.redeem()Public

Used inGuests

  • Permission: None: public. The token from the invitation email is the proof.
  • Audited as: guest:redeem, with the new guest as the actor and the invitation, inviter, sponsor, grants, and access end in the metadata.
  • Errors: INVITATION_INVALID when the token is unknown, used, revoked, or lapsed, when the inviter is inactive or can no longer grant what it grants, or when the sponsor can no longer sponsor guests; GUEST_NOT_ALLOWED when the host's inbound or the home organization's outbound settings no longer admit the person; TENANT_UNAVAILABLE when the tenant or an ancestor is not active; METHOD_NOT_ALLOWED when the tenant does not accept password sign-in; WEAK_PASSWORD or BREACHED_PASSWORD; IDENTITY_EXISTS when an account with the address was created meanwhile; LIMIT_EXCEEDED at the tenant's member limit; SOD_CONFLICT; INVARIANT_VIOLATION; RATE_LIMITED; INVALID_INPUT without a token, name, or password.

The email counts as verified, because the invitation reached it. The guest's expiresAt is redemption plus the invitation's accessDays, and its roles, groups, and packages end then too (a package's maximum duration can end its assignment sooner). Birthright rules that test identity.guest apply right away. The result is the new public identity, with its guest marker, plus either { token, session } or an MFA challenge (mfaRequired: true) when the tenant requires MFA. Over HTTP a response that issues a session sets the session cookie. Everything happens in one transaction, so a failure leaves the invitation usable. Attempts are limited per tenant (500), client address (20), and token (10) within the rate-limit window.

const result = await client.guests.redeem({ tenantId, token, name: 'Gina', password });
if ('mfaRequired' in result) {
  // enroll or verify the second factor, then continue
}
Input

Prop

Type

Returns

One of object & SessionResult | object & MfaRequired.

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/guests/redeem" \
  -H "Content-Type: application/json" \
  -H "X-Better-IAM: 1" \
  -d '{
  "tenantId": "<tenantId>",
  "token": "<token>",
  "name": "<name>",
  "password": "<password>"
}'
Signature
iam.api.guests.redeem(
  input: { tenantId: string; token: string; name: string; password: string },
): Promise<EnrollmentResult>

remove

Removes a guest: disables them and takes away everything they hold, in one transaction.

POST/api/iam/guests/remove
client.guests.remove()Credential

Used inGuests

  • Permission: iam:guests:manage on iam/guests/{identityId}, and a recent sign-in.
  • Audited as: iam:guests:manage, plus guest:remove with the reason, the sponsor, and the counts.
  • Errors: INVALID_TRANSITION (409) when the guest was already removed or converted; INVALID_INPUT without a reason (up to 512 characters), for the caller themselves, or for an owner (transfer ownership first); RECENT_AUTH_REQUIRED; NOT_FOUND.

The identity is disabled; its sessions, keys, and delegations end; every role binding, group and team membership, package assignment, activation, and relationship it holds is removed, whichever authority granted it; its pending requests and invitations are cancelled; its grant authorities are revoked; and the guest account closes as removed. A guest whose access already ended can be removed too. The result is the guest with the counts of sessions, bindings, memberships, and packages removed.

Input

Prop

Type

Returns

A GuestRemoval 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/guests/remove" \
  -H "Authorization: Bearer $BETTER_IAM_TOKEN" \
  -H "Content-Type: application/json" \
  -H "X-Better-IAM: 1" \
  -d '{
  "tenantId": "<tenantId>",
  "identityId": "<identityId>",
  "reason": "<reason>"
}'
Signature
iam.api.guests.remove(
  credential: CredentialInput,
  input: { tenantId: string; identityId: string; reason: string },
): Promise<GuestRemoval>

resendInvitation

Sends a pending or lapsed guest invitation again with a new token and a new lifetime.

POST/api/iam/guests/resendInvitation
client.guests.resendInvitation()Credential

Used inGuests

  • Permission: iam:guests:invite on iam/guests/invitations/{id}.
  • Audited as: iam:guests:invite, plus guest:invitation-resend with the new lapse.
  • Errors: INVALID_TRANSITION (409) for a redeemed or revoked invitation; CONFLICT (409) when the address now belongs to someone in the tenant; GUEST_NOT_ALLOWED when the settings no longer admit it; INVALID_SPONSOR when the sponsor can no longer sponsor guests; INVITATION_INVALID when the original inviter is inactive or can no longer grant what the invitation grants; DELIVERY_REQUIRED; TENANT_INACTIVE when the tenant is not active; INVALID_INPUT for an expiresInDays outside 1 to 30; NOT_FOUND.

The earlier token stops working. The invitation keeps its inviter, sponsor, and grants, and only goes out when it could be redeemed, since redemption checks the same things again. expiresInDays defaults to 14.

Input

Prop

Type

Returns

A GuestInvitationView 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/guests/resendInvitation" \
  -H "Authorization: Bearer $BETTER_IAM_TOKEN" \
  -H "Content-Type: application/json" \
  -H "X-Better-IAM: 1" \
  -d '{
  "tenantId": "<tenantId>",
  "invitationId": "<invitationId>"
}'
Signature
iam.api.guests.resendInvitation(
  credential: CredentialInput,
  input: { tenantId: string; invitationId: string; expiresInDays?: number },
): Promise<GuestInvitationView>

revokeInvitation

Withdraws a pending guest invitation, so its token stops working.

POST/api/iam/guests/revokeInvitation
client.guests.revokeInvitation()Credential
  • Permission: iam:guests:manage on iam/guests/invitations/{id}.
  • Audited as: iam:guests:manage, plus guest:invitation-revoke.
  • Errors: INVALID_TRANSITION (409) when the invitation is not pending; NOT_FOUND when it is not in this tenant.
Input

Prop

Type

Returns

A GuestInvitationView 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/guests/revokeInvitation" \
  -H "Authorization: Bearer $BETTER_IAM_TOKEN" \
  -H "Content-Type: application/json" \
  -H "X-Better-IAM: 1" \
  -d '{
  "tenantId": "<tenantId>",
  "invitationId": "<invitationId>"
}'
Signature
iam.api.guests.revokeInvitation(
  credential: CredentialInput,
  input: { tenantId: string; invitationId: string },
): Promise<GuestInvitationView>

setSponsor

Gives an active guest a new sponsor and clears a missing-sponsor flag.

POST/api/iam/guests/setSponsor
client.guests.setSponsor()Credential
  • Permission: iam:guests:manage on iam/guests/{identityId}, and a recent sign-in.
  • Audited as: iam:guests:manage, plus guest:sponsor-change with from, to, and reason: 'administrator'.
  • Errors: INVALID_SPONSOR when the new sponsor is not an active member who is not a guest; INVALID_TRANSITION (409) when the guest account is no longer active (expired, removed, or converted); RECENT_AUTH_REQUIRED; NOT_FOUND.

Decisions see the new principal.guestSponsorId from the next request.

Input

Prop

Type

Returns

A GuestView 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/guests/setSponsor" \
  -H "Authorization: Bearer $BETTER_IAM_TOKEN" \
  -H "Content-Type: application/json" \
  -H "X-Better-IAM: 1" \
  -d '{
  "tenantId": "<tenantId>",
  "identityId": "<identityId>",
  "sponsorId": "<sponsorId>"
}'
Signature
iam.api.guests.setSponsor(
  credential: CredentialInput,
  input: { tenantId: string; identityId: string; sponsorId: string },
): Promise<GuestView>

Was this page helpful?

Better IAM is created by Sean Filimon

Last updated

On this page