> ## Documentation Index
> Fetch the complete documentation index at: https://docs-dev-actions-triggers-prototype.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

> Learn about the post-login Action trigger's API object.

# API Object

The API object for the post-login Actions trigger exposes methods for controlling access, customizing tokens, managing authentication state, configuring redirects, and more.

## `api.access`

Modify the access of the user that is logging in, such as rejecting the login attempt.

<ParamField body="api.access.deny(reason)" type="void">
  Mark the current login attempt as denied. This prevents the end-user from completing the login flow. This will *NOT* cancel other user-related side-effects (such as metadata changes) requested by this Action.

  ```js Example theme={null}
  exports.onExecutePostLogin = async (event, api) => {
    api.access.deny('You are not allowed to log in.');
  };
  ```

  **Parameters**

  <Expandable title="Parameters">
    <ParamField body="reason" type="string">
      A human-readable explanation for rejecting the login. This may be presented directly in end-user interfaces.
    </ParamField>
  </Expandable>
</ParamField>

## `api.accessToken`

Request changes to the access token being issued.

<ParamField body="api.accessToken.setCustomClaim(key, value)" type="void">
  Set a custom claim on the access token issued upon completion of the login flow.

  ```js Example theme={null}
  exports.onExecutePostLogin = async (event, api) => {
    api.accessToken.setCustomClaim('https://example.com/role', 'admin');
  };
  ```

  **Parameters**

  <Expandable title="Parameters">
    <ParamField body="key" type="string">
      Name of the claim (note that this may need to be a fully-qualified URL).
    </ParamField>

    <ParamField body="value" type="unknown">
      The value of the claim.
    </ParamField>
  </Expandable>
</ParamField>

<ParamField body="api.accessToken.addScope(scope)" type="void">
  Add a scope to the access token issued upon completion of the login flow.

  ```js Example theme={null}
  exports.onExecutePostLogin = async (event, api) => {
    api.accessToken.addScope('read:reports');
  };
  ```

  **Parameters**

  <Expandable title="Parameters">
    <ParamField body="scope" type="string">
      The scope to be added.
    </ParamField>
  </Expandable>
</ParamField>

<ParamField body="api.accessToken.removeScope(scope)" type="void">
  Remove a scope from the access token issued upon completion of the login flow.

  ```js Example theme={null}
  exports.onExecutePostLogin = async (event, api) => {
    api.accessToken.removeScope('admin:full');
  };
  ```

  **Parameters**

  <Expandable title="Parameters">
    <ParamField body="scope" type="string">
      The scope to be removed.
    </ParamField>
  </Expandable>
</ParamField>

## `api.idToken`

Request changes to the ID token being issued.

<ParamField body="api.idToken.setCustomClaim(key, value)" type="void">
  Set a custom claim on the ID token issued upon completion of the login flow.

  ```js Example theme={null}
  exports.onExecutePostLogin = async (event, api) => {
    api.idToken.setCustomClaim('https://example.com/department', 'engineering');
  };
  ```

  **Parameters**

  <Expandable title="Parameters">
    <ParamField body="key" type="string">
      Name of the claim (note that this may need to be a fully-qualified URL).
    </ParamField>

    <ParamField body="value" type="unknown">
      The value of the claim.
    </ParamField>
  </Expandable>
</ParamField>

## `api.authentication`

Request changes to the authentication state of the current user's session.

<ParamField body="api.authentication.challengeWith(factor, options)" type="void">
  Request a challenge for MFA using the supplied factor. Subsequent Actions will not run until the challenge is fulfilled.

  ```js Challenge with a specific factor theme={null}
  api.authentication.challengeWith({ type: 'phone', options: { preferredMethod: 'both' } });
  ```

  ```js Challenge with additional factors theme={null}
  api.authentication.challengeWith({ type: 'otp' }, {
    additionalFactors: [{ type: 'push-notification' }, { type: 'phone' }]
  });
  ```

  **Parameters**

  <Expandable title="Parameters">
    <ParamField body="factor" type="object">
      The factor to use for the initial challenge.

      <Expandable title="factor properties">
        <ParamField body="type" type="string">
          The factor type. Allowed values: `otp`, `email`, `webauthn-platform`, `webauthn-roaming`, `recovery-code`, `push-notification`, `phone`.
        </ParamField>

        <ParamField body="options" type="object">
          Additional options for the factor type. Optional.
        </ParamField>
      </Expandable>
    </ParamField>

    <ParamField body="options" type="object">
      Optional.

      <Expandable title="options properties">
        <ParamField body="additionalFactors" type="array of objects">
          Additional factors the user may choose from.
        </ParamField>
      </Expandable>
    </ParamField>
  </Expandable>
</ParamField>

<ParamField body="api.authentication.challengeWithAny(factors)" type="void">
  Request a challenge for MFA using any of the supplied factors, showing a factor selection screen.

  ```js Example theme={null}
  exports.onExecutePostLogin = async (event, api) => {
    api.authentication.challengeWithAny([{ type: 'otp' }, { type: 'email' }]);
  };
  ```

  **Parameters**

  <Expandable title="Parameters">
    <ParamField body="factors" type="array of objects">
      An array of factors.
    </ParamField>
  </Expandable>
</ParamField>

<ParamField body="api.authentication.enrollWith(factor, options)" type="void">
  Request an enrollment for MFA using the supplied factor.

  ```js Example theme={null}
  exports.onExecutePostLogin = async (event, api) => {
    api.authentication.enrollWith({ type: 'otp' }, {
      additionalFactors: [{ type: 'push-notification' }]
    });
  };
  ```

  **Parameters**

  <Expandable title="Parameters">
    <ParamField body="factor" type="object">
      The factor to use for enrollment.

      <Expandable title="factor properties">
        <ParamField body="type" type="string">
          The factor type. Allowed values: `otp`, `webauthn-platform`, `webauthn-roaming`, `recovery-code`, `push`, `push-notification`.
        </ParamField>

        <ParamField body="options" type="object">
          Additional options for the factor type. Optional.
        </ParamField>
      </Expandable>
    </ParamField>

    <ParamField body="options" type="object">
      Optional.

      <Expandable title="options properties">
        <ParamField body="additionalFactors" type="array of objects">
          Additional factors the user may choose from.
        </ParamField>
      </Expandable>
    </ParamField>
  </Expandable>
</ParamField>

<ParamField body="api.authentication.recordMethod(provider_url)" type="void">
  Indicate that a custom authentication method has been completed. Only available from within `onContinuePostLogin` after a redirect.

  ```js Example theme={null}
  exports.onContinuePostLogin = async (event, api) => {
    api.authentication.recordMethod('https://my-app.example.com/mfa');
  };
  ```

  **Parameters**

  <Expandable title="Parameters">
    <ParamField body="provider_url" type="string">
      An `http:` or `https:` URL that uniquely represents the completed authentication method.
    </ParamField>
  </Expandable>
</ParamField>

<ParamField body="api.authentication.setPrimaryUser(primary_user_id)" type="void">
  Change the primary user for the login transaction. Use in account-linking scenarios where the initiating identity is now a secondary identity of an existing user.

  **IMPORTANT**: Insecurely linking accounts can allow malicious actors to access legitimate user accounts. The identity used to authenticate *must* be among the secondary identities of the referenced user.

  ```js Example theme={null}
  exports.onExecutePostLogin = async (event, api) => {
    api.authentication.setPrimaryUser('auth0|existing_user_id');
  };
  ```

  **Parameters**

  <Expandable title="Parameters">
    <ParamField body="primary_user_id" type="string">
      The user ID of the user for whom tokens should be issued (the `sub` claim).
    </ParamField>
  </Expandable>
</ParamField>

## `api.multifactor`

Set or remove the requirement for MFA on the login attempt.

<ParamField body="api.multifactor.enable(provider, options)" type="void">
  Enable MFA for this login flow. Users must complete the configured MFA challenge before completing login.

  ```js Example theme={null}
  exports.onExecutePostLogin = async (event, api) => {
    api.multifactor.enable('any', { allowRememberBrowser: true });
  };
  ```

  **Parameters**

  <Expandable title="Parameters">
    <ParamField body="provider" type="string">
      The MFA provider to use or `"any"` to use any configured provider. Allowed values: `duo`, `none`, `guardian`, `google-authenticator`, `any`.
    </ParamField>

    <ParamField body="options" type="object">
      Optional.

      <Expandable title="options properties">
        <ParamField body="allowRememberBrowser" type="boolean">
          When `google-authenticator` or `duo`, prompts MFA once every 30 days. When `guardian`, shows enrollment checkbox. Defaults to `false`.
        </ParamField>

        <ParamField body="providerOptions" type="object">
          Additional options for the `duo` provider only. Optional.
        </ParamField>
      </Expandable>
    </ParamField>
  </Expandable>
</ParamField>

## `api.redirect`

Configure and initiate external redirects.

<ParamField body="api.redirect.encodeToken(options)" type="string">
  Create a signed session token for use as a query string parameter in a redirect. The target endpoint verifies authenticity using a shared secret.

  ```js Example theme={null}
  exports.onExecutePostLogin = async (event, api) => {
    const token = api.redirect.encodeToken({
      secret: event.secrets.MY_SECRET,
      payload: { userId: event.user.user_id },
      expiresInSeconds: 300,
    });
    api.redirect.sendUserTo('https://my-app.example.com/verify', { query: { token } });
  };
  ```

  **Parameters**

  <Expandable title="Parameters">
    <ParamField body="options" type="object">
      <Expandable title="options properties">
        <ParamField body="secret" type="string">
          A secret used to sign the JWT. Store as an Action secret and retrieve via `event.secrets['<secret_name>']`.
        </ParamField>

        <ParamField body="payload" type="object">
          The data to pass to the redirect target whose authenticity must be provable.
        </ParamField>

        <ParamField body="expiresInSeconds" type="number">
          Number of seconds before this token expires. Optional.
        </ParamField>
      </Expandable>
    </ParamField>
  </Expandable>
</ParamField>

<ParamField body="api.redirect.sendUserTo(url, options)" type="void">
  Trigger a browser redirect to the target URL immediately after this action completes.

  ```js Example theme={null}
  exports.onExecutePostLogin = async (event, api) => {
    api.redirect.sendUserTo('https://my-app.example.com/verify', {
      query: { user_id: event.user.user_id },
    });
  };
  ```

  **Parameters**

  <Expandable title="Parameters">
    <ParamField body="url" type="string">
      The URL to redirect the user to.
    </ParamField>

    <ParamField body="options" type="object">
      Optional.

      <Expandable title="options properties">
        <ParamField body="query" type="object">
          Additional query string parameters to append to the redirect URL.
        </ParamField>
      </Expandable>
    </ParamField>
  </Expandable>
</ParamField>

<ParamField body="api.redirect.validateToken(options)" type="object">
  Retrieve and verify data encoded in a JWT passed to the `/continue` endpoint.

  ```js Example theme={null}
  exports.onContinuePostLogin = async (event, api) => {
    const payload = api.redirect.validateToken({
      secret: event.secrets.MY_SECRET,
      tokenParameterName: 'token',
    });
  };
  ```

  **Parameters**

  <Expandable title="Parameters">
    <ParamField body="options" type="object">
      <Expandable title="options properties">
        <ParamField body="secret" type="string">
          The secret used to verify the JWT signature.
        </ParamField>

        <ParamField body="tokenParameterName" type="string">
          The name of the query or body parameter sent to the `/continue` endpoint. Optional.
        </ParamField>
      </Expandable>
    </ParamField>
  </Expandable>
</ParamField>

## `api.user`

Make changes to the metadata of the user that is logging in.

<ParamField body="api.user.setAppMetadata(key, value)" type="void">
  Set application-specific metadata for the user. This function works only with metadata in object format.

  ```js Example theme={null}
  exports.onExecutePostLogin = async (event, api) => {
    api.user.setAppMetadata('plan', 'enterprise');
  };
  ```

  **Parameters**

  <Expandable title="Parameters">
    <ParamField body="key" type="string">
      The metadata property to be set.
    </ParamField>

    <ParamField body="value" type="unknown">
      The value of the metadata property. Set to `null` to remove the property.
    </ParamField>
  </Expandable>
</ParamField>

<ParamField body="api.user.setUserMetadata(key, value)" type="void">
  Set general metadata for the user that is logging in. This function works only with metadata in object format.

  ```js Example theme={null}
  exports.onExecutePostLogin = async (event, api) => {
    api.user.setUserMetadata('last_login_ip', event.request.ip);
  };
  ```

  **Parameters**

  <Expandable title="Parameters">
    <ParamField body="key" type="string">
      The metadata property to be set.
    </ParamField>

    <ParamField body="value" type="unknown">
      The value of the metadata property. Set to `null` to remove the property.
    </ParamField>
  </Expandable>
</ParamField>

## `api.session`

Request changes to the current user's session.

<ParamField body="api.session.revoke(reason, options)" type="void">
  \[Enterprise] Revoke the current user session and mark the login attempt as denied.

  ```js Revoke the session while preserving refresh tokens theme={null}
  api.session.revoke('reason', { preserveRefreshTokens: true });
  ```

  **Parameters**

  <Expandable title="Parameters">
    <ParamField body="reason" type="string">
      A human-readable explanation for rejecting the login.
    </ParamField>

    <ParamField body="options" type="object">
      Optional.

      <Expandable title="options properties">
        <ParamField body="preserveRefreshTokens" type="boolean">
          If true, ends the session but keeps refresh tokens. Defaults to `false`.
        </ParamField>
      </Expandable>
    </ParamField>
  </Expandable>
</ParamField>

<ParamField body="api.session.setExpiresAt(absolute)" type="void">
  \[Enterprise] Sets a new absolute expiration time for the current session.

  ```js Example theme={null}
  exports.onExecutePostLogin = async (event, api) => {
    api.session.setExpiresAt(Date.now() + 8 * 60 * 60 * 1000); // 8 hours
  };
  ```

  **Parameters**

  <Expandable title="Parameters">
    <ParamField body="absolute" type="number">
      The new absolute expiration time in milliseconds since the unix epoch.
    </ParamField>
  </Expandable>
</ParamField>

<ParamField body="api.session.setMetadata(key, value)" type="void">
  \[Enterprise] Sets a key-value pair in the metadata object of the current session.

  ```js Example theme={null}
  exports.onExecutePostLogin = async (event, api) => {
    api.session.setMetadata('login_method', 'sso');
  };
  ```

  **Parameters**

  <Expandable title="Parameters">
    <ParamField body="key" type="string">
      The key to set in the metadata object.
    </ParamField>

    <ParamField body="value" type="string">
      The value to set. Null values delete the key.
    </ParamField>
  </Expandable>
</ParamField>

## `api.refreshToken`

Request changes to the current user's refresh token.

<ParamField body="api.refreshToken.revoke(reason)" type="void">
  \[Enterprise] Revoke the current refresh token and deny the refresh token exchange.

  ```js Example theme={null}
  exports.onExecutePostLogin = async (event, api) => {
    api.refreshToken.revoke('Token has been invalidated.');
  };
  ```

  **Parameters**

  <Expandable title="Parameters">
    <ParamField body="reason" type="string">
      A human-readable explanation for rejecting the refresh token exchange.
    </ParamField>
  </Expandable>
</ParamField>

<ParamField body="api.refreshToken.setMetadata(key, value)" type="void">
  \[Enterprise] Sets a key-value pair in the metadata object of the current refresh token.

  ```js Example theme={null}
  exports.onExecutePostLogin = async (event, api) => {
    api.refreshToken.setMetadata('issued_for', 'mobile_app');
  };
  ```

  **Parameters**

  <Expandable title="Parameters">
    <ParamField body="key" type="string">
      The key to set in the metadata object.
    </ParamField>

    <ParamField body="value" type="string">
      The value to set. Null values delete the key.
    </ParamField>
  </Expandable>
</ParamField>

## `api.validation`

Prevent user from logging in by signaling a validation error.

<ParamField body="api.validation.error(errorCode, errorMessage)" type="void">
  Throw a validation error to prevent login.

  ```js Example theme={null}
  exports.onExecutePostLogin = async (event, api) => {
    api.validation.error('access_denied', 'User is not allowed to log in.');
  };
  ```

  **Parameters**

  <Expandable title="Parameters">
    <ParamField body="errorCode" type="string">
      A customer-defined error code for the validation error.
    </ParamField>

    <ParamField body="errorMessage" type="string">
      A customer-defined message for the validation error.
    </ParamField>
  </Expandable>
</ParamField>

## `api.prompt`

Render a custom prompt screen.

<ParamField body="api.prompt.render(promptId, promptOptions)" type="void">
  Render a custom prompt during the login flow.

  ```js Example theme={null}
  exports.onExecutePostLogin = async (event, api) => {
    api.prompt.render('my-custom-prompt', { vars: { name: event.user.name } });
  };
  ```

  **Parameters**

  <Expandable title="Parameters">
    <ParamField body="promptId" type="string">
      The prompt ID.
    </ParamField>

    <ParamField body="promptOptions" type="object">
      The render options. Optional.

      <Expandable title="promptOptions properties">
        <ParamField body="fields" type="object">
          Key-value pairs to populate field values (client-side). Optional.
        </ParamField>

        <ParamField body="vars" type="object">
          Key-value pairs to inject variables (server-side). Optional.
        </ParamField>
      </Expandable>
    </ParamField>
  </Expandable>
</ParamField>

## `api.samlResponse`

Configure custom SAML response attributes.

<ParamField body="api.samlResponse.setAttribute(attribute, value)" type="void">
  Set attributes on the SAML assertion issued to the authenticated user.

  ```js Example theme={null}
  exports.onExecutePostLogin = async (event, api) => {
    api.samlResponse.setAttribute('http://schemas.example.com/role', 'admin');
  };
  ```

  **Parameters**

  <Expandable title="Parameters">
    <ParamField body="attribute" type="string">The SAML attribute to set.</ParamField>
    <ParamField body="value" type="unknown">The value of the SAML claim. Set to `null` or `undefined` to remove the claim.</ParamField>
  </Expandable>
</ParamField>

<ParamField body="api.samlResponse.setAudience(audience)" type="void">
  Set the audience of the SAML assertion. Default is the issuer on SAMLRequest.

  ```js Example theme={null}
  exports.onExecutePostLogin = async (event, api) => {
    api.samlResponse.setAudience('https://sp.example.com');
  };
  ```

  **Parameters**

  <Expandable title="Parameters">
    <ParamField body="audience" type="string">The audience value.</ParamField>
  </Expandable>
</ParamField>

<ParamField body="api.samlResponse.setEncryptionAlgorithm(encryptionAlgorithm)" type="void">
  Set the encryption algorithm for the SAML assertion. Default is `aes256-cbc`.

  ```js Set the encryption algorithm to aes256-gcm (recommended) theme={null}
  api.samlResponse.setEncryptionAlgorithm('aes256-gcm');
  ```

  **Parameters**

  <Expandable title="Parameters">
    <ParamField body="encryptionAlgorithm" type="string">
      The algorithm to use. Allowed values: `aes256-gcm`.
    </ParamField>
  </Expandable>
</ParamField>

## `api.groups`

Get information about user group membership.

<ParamField body="api.groups.getUserGroups(params)" type="Promise<object>">
  Get the paginated list of groups the user belongs to.

  ```js Example theme={null}
  exports.onExecutePostLogin = async (event, api) => {
    const groups = await api.groups.getUserGroups({ take: 10 });
  };
  ```

  **Parameters**

  <Expandable title="Parameters">
    <ParamField body="params" type="object">
      Pagination options. Optional.

      <Expandable title="params properties">
        <ParamField body="take" type="number">Number of results to return. Optional.</ParamField>
        <ParamField body="from" type="string">Cursor for pagination. Optional.</ParamField>
      </Expandable>
    </ParamField>
  </Expandable>
</ParamField>

<ParamField body="api.groups.hasGroupMembership(groups)" type="Promise<object>">
  Check if the user is a member of any of the specified groups.

  ```js Example theme={null}
  exports.onExecutePostLogin = async (event, api) => {
    const result = await api.groups.hasGroupMembership(['admins', 'editors']);
  };
  ```

  **Parameters**

  <Expandable title="Parameters">
    <ParamField body="groups" type="array of strings">
      An array of group identifiers (IDs or names) to check membership against.
    </ParamField>
  </Expandable>
</ParamField>

## `api.cache`

Store and retrieve data that persists across executions.

<ParamField body="api.cache.delete(key)" type="void">
  Delete a cached record at the supplied key if it exists.

  ```js Example theme={null}
  exports.onExecutePostLogin = async (event, api) => {
    api.cache.delete('my-key');
  };
  ```

  **Parameters**

  <Expandable title="Parameters">
    <ParamField body="key" type="string">
      The key of the cache record to delete.
    </ParamField>
  </Expandable>
</ParamField>

<ParamField body="api.cache.get(key)" type="object | undefined">
  Retrieve a cached record at the supplied key. If found, access the value via `record.value`.

  ```js Example theme={null}
  exports.onExecutePostLogin = async (event, api) => {
    const record = api.cache.get('my-key');
    if (record) console.log(record.value);
  };
  ```

  **Parameters**

  <Expandable title="Parameters">
    <ParamField body="key" type="string">
      The key of the record stored in the cache.
    </ParamField>
  </Expandable>
</ParamField>

<ParamField body="api.cache.set(key, value, options)" type="void">
  Store or update a string value in the cache at the specified key. Values are scoped to the Trigger and subject to the [Actions Cache Limits](https://auth0.com/docs/customize/actions/limitations). If no lifetime is specified, a default lifetime of 15 minutes will be used.

  **Important**: This cache is designed for short-lived, ephemeral data. Items may not be available in later transactions even if they are within their supplied lifetime.

  ```js Example theme={null}
  exports.onExecutePostLogin = async (event, api) => {
    api.cache.set('my-key', 'my-value', { ttl: 60000 });
  };
  ```

  **Parameters**

  <Expandable title="Parameters">
    <ParamField body="key" type="string">
      The key of the record to be stored.
    </ParamField>

    <ParamField body="value" type="string">
      The value of the record to be stored.
    </ParamField>

    <ParamField body="options" type="CacheSetOptions">
      Options for adjusting cache behavior. Optional.

      <Expandable title="options properties">
        <ParamField body="expires_at" type="number">
          The absolute expiry time in milliseconds since the unix epoch. *Note*: Do not supply if `ttl` is also provided; the earlier expiry will be used.
        </ParamField>

        <ParamField body="ttl" type="number">
          The time-to-live in milliseconds. *Note*: Do not supply if `expires_at` is also provided; the earlier expiry will be used.
        </ParamField>
      </Expandable>
    </ParamField>
  </Expandable>
</ParamField>
