ServiceNow IntegrationHub | Entitle

BeyondTrust Entitle for ServiceNow lets your users request just-in-time (JIT) access to applications, systems, and other resources governed by Entitle, directly from the ServiceNow Service Catalog. Each request goes through your configured approval process. Entitle fulfills it, and ServiceNow tracks it to completion. When the approved duration expires, Entitle revokes access automatically, so no manual cleanup is required.

📘

This guide refers to the Entitle Spoke, or simply the Spoke. A spoke is a ServiceNow IntegrationHub component that packages actions for connecting to a third-party system. The Entitle Spoke handles all API calls between ServiceNow and Entitle. It is installed alongside the main application but does not require further interaction after setup.

Key features

  • Native catalog experience: A ready-to-use Request Entitle Access catalog item offers each user only the resources they are eligible for in Entitle. You can narrow it to bundles only or roles only.
  • Eligibility caching: The app caches each user's eligibility and refreshes it automatically, so the request form loads quickly while staying close to current. Entitle still checks eligibility at submission.
  • Configurable approvals: A built-in approval chain routes each request to the manager or a default group, with optional Change Advisory Board (CAB) escalation for long durations. You can replace it entirely with your own approval logic.
  • Time-limited access: Durations come from each resource's settings in Entitle or from your configured fallback list. Entitle revokes access automatically when the duration expires.
  • Status reconciliation: Push updates from Entitle's webhook, which is enabled by default, drive every request to closure and keep requesters informed. An optional polling fallback is also available.
  • Extension hooks: Four override points let you change the application's behavior without modifying it. Three customize individual steps (approval, pre-submit validation, and notifications), and one replaces the entire fulfillment flow.

Architecture

The integration consists of two scoped applications:

ApplicationScopePurpose
BeyondTrust Entitle Spokex_bets_entitle_spoClient for the Entitle API. It contains six IntegrationHub actions built on native Representational State Transfer (REST) steps, the Entitle - Get User Eligibility (All Pages) subflow, an EntitleError normalizer for API failures, and a single Connection & Credential Alias. It contains no business logic, no tables, and no configuration of its own.
BeyondTrust Entitlex_bets_entitleEverything else: the catalog item, eligibility caching, the fulfillment flow, approvals, status reconciliation, configuration, and the customization hooks. Status reconciliation uses the webhook by default, with optional polling.

The main application does all its Entitle communication through the Spoke and cannot function without it.

Request workflow

  1. A user with the x_bets_entitle.requester role opens Request Entitle Access in the catalog and picks a resource they are eligible for, a duration, and a justification.
  2. The Access Request flow validates the request and runs approval, using either the built-in chain or your custom Approval Hook. It then runs pre-submit validation and submits the request to Entitle through the Spoke.
  3. ServiceNow tracks the Entitle request to a terminal state, normally through Entitle's push webhook, or through the optional polling flow if you have activated it. ServiceNow then closes the requested item (RITM) and notifies the requester.
  4. Entitle provisions the access and automatically revokes it when the duration expires.

Prerequisites

Ensure you have:

BeyondTrust Entitle

  • An Entitle tenant, and an Entitle administrator account that can manage Org settings, where you create an API token in Step 2
  • Your tenant's regional API base URL:
    • Global: https://api.entitle.io/public/v1
    • US: https://api.us.entitle.io/public/v1
    • Canada: https://api.ca.entitle.io/public/v1

ServiceNow

  • A ServiceNow instance on a supported release: Zurich or later
  • Flow Designer and IntegrationHub available, through the com.glide.hub.integration plugin
  • Rights to install applications and administer Connections & Credentials
  • Outbound network access from the instance to the Entitle API host for your region
🚧

Important

The Spoke is a prerequisite of the main application and must be installed first. The main application declares the minimum Spoke version it needs, and the platform enforces it at install time.

Initial setup

Step 1: Install the applications (ServiceNow)

  1. In ServiceNow, go to All > System Applications > All Available Applications > All.
  2. Install BeyondTrust Entitle Spoke (x_bets_entitle_spo) first.
  3. Install BeyondTrust Entitle (x_bets_entitle) second. The app declares a dependency on the Spoke, including its minimum version. If you install in the wrong order, or over a Spoke that is too old, the dependency check fails.

When you install the main app, it automatically:

  • Seeds the single Entitle Configuration record, named Default, with opt-in defaults: no duration options selected, Log Level set to Error, and Webhook Enabled set to true. For every value, see the Configuration reference.
  • Creates the Request Entitle Access catalog item in a BeyondTrust Entitle category within the standard Service Catalog.
  • Creates the BeyondTrust Entitle navigation menu, visible to x_bets_entitle.admin, with four modules: Configuration, Requests, Help, and App Privacy Policy.
  • Activates one recurring job: the daily Purge Expired Entitle Eligibility cleanup job. The app also installs the optional Status Reconciliation polling flow but leaves it inactive. For more information, see Enable status polling.
ℹ️

Nothing tenant-specific ships with the app. You set the Entitle connection URL and API token, the webhook service account, approval groups, duration options, and hook references in the steps that follow.

Step 2: Create the Entitle API token (Entitle)

  1. Sign in to Entitle as an administrator and open Org settings.
  2. Open the Tokens tab and click Add. Choose an API token, not an Agent token.
  3. Enter a Token name that identifies its use, for example ServiceNow integration. The name must be 2–250 characters.
  4. Select an Expiration that matches your credential policy, and record the date. The integration stops working when the token expires. For more information see Credential rotation.
  5. Click Reveal token, copy the value, and store it in your secrets manager. Entitle shows the value only at creation time. If you lose it, Revoke the token in the same list and create a new one.

The Spoke authenticates to Entitle with this API token. It is an organization-level credential that is not tied to any user, so it keeps working when individual administrators leave. Do not use a personal access token for the integration. Personal access tokens are bound to the user who created them and are meant for that user's own API access.

🚧

Important

The API token carries administrator rights across your Entitle organization. Treat it as a privileged secret. Store it only in your secrets manager and in the ServiceNow credential record you create in the next step, which encrypts it. Never store it in scripts, tickets, or chat.

Step 3: Connect ServiceNow to your Entitle tenant (ServiceNow)

  1. In ServiceNow, go to All > Connections & Credentials > Credentials.

  2. Click New, and choose API Key Credentials.

  3. Give it a name, for example Entitle API Key.

  4. Paste the API token from Step 2 into the API Key field.

  5. Click Submit. ServiceNow encrypts the value on save and sends it as a Bearer token on every call.

  6. Go to All > Connections & Credentials > Connection & Credential Aliases and open EntitleConnectionAlias (x_bets_entitle_spo.EntitleConnectionAlias).

  7. In its Connections related list, click New and create an HTTP(s) Connection.

  8. Give it a name, for example Entitle API.

  9. Set Credential to the credential from step 1, and set Connection URL to your regional Entitle API base URL, listed in Prerequisites.

  10. Click Submit.

  11. Verify the connection. Go to All > System Definition > Scripts - Background, leave the scope set to global, and run:

    var out = sn_fd.FlowAPI.getRunner()
        .action('x_bets_entitle_spo.entitle__list_bundles')
        .inForeground()
        .withInputs({ limit: 5 })
        .run()
        .getOutputs();
    gs.info(out.result_json);

    A result with "ok": true and bundle data confirms connectivity and credentials. A result with "ok": false and "code": "auth_error" means Entitle rejected the token.

The Spoke:

  • Reads the Entitle base URL and API token through a single Connection & Credential Alias, EntitleConnectionAlias.
  • Installs the alias with nothing attached, which is why you create the credential and connection yourself.
  • Publishes its actions for cross-scope use, so the verification script can call them from the global scope. Use the global scope, because Scripts - Background does not offer the scopes of applications installed from the ServiceNow Store or a company application repository.
  • Has no script-include client; its actions and subflow are its only surface.
ℹ️

The internal action name x_bets_entitle_spo.entitle__list_bundles contains a double underscore.

Step 4: Assign roles (ServiceNow)

  1. In ServiceNow, go to All > User Administration > Users or Groups.
  2. Grant x_bets_entitle.admin to the people who will administer the integration.
  3. Grant x_bets_entitle.requester or x_bets_entitle.proxy_requester to the users who may request access. A group is usually the easiest way to grant these roles.
  4. Do not assign x_bets_entitle.api here. It belongs only to the webhook service account you create in Step 6.

The app defines four roles:

RoleAssign toPurpose
x_bets_entitle.adminIntegration administratorsFull administrative access: the navigation menu, the Configuration record, and all app data tables.
x_bets_entitle.requesterUsers who may request accessMakes the catalog category and the Request Entitle Access item visible. The Entitle Requesters user criteria on this role gates the item.
x_bets_entitle.proxy_requesterDelegates and coordinatorsContains the requester role, so it grants everything requester grants. It also adds the On Behalf Of field to the request form, for submitting on another user's behalf.
x_bets_entitle.apiOnly the webhook service accountGrants nothing except permission to call the inbound events endpoint. Do not assign it to people.

Step 5: Configure approvals and durations (ServiceNow)

  1. In ServiceNow, go to BeyondTrust Entitle > Configuration. This opens the classic UI16 or Polaris form.

    The form opens directly on the single Default record. Use its Save button to stay on the form.

  2. In the Approvals section of the main form, set a Default Approval Group. The built-in approval chain uses it whenever a requester has no manager. If neither a manager nor a default group is available, the chain rejects the request outright.

  3. On the Request Durations tab, use the checkbox picker to select at least one fallback duration option. The request form offers these when an Entitle resource doesn't define its own allowed durations. The app ships with none selected, and no one can submit a request until you select at least one. Optionally, set a Default Duration from among them.

  4. Click Save.

  5. (Optional) To require a second approval for long-duration requests, go to the CAB escalation section of the main form and set a CAB Approval Group and a CAB Escalation Duration (Days). See The built-in approval chain.

  6. (Optional) In the Offered Resource Types field on the main form, leave the default of Bundles and Roles, or narrow the request form to Bundles only or Roles only. This setting filters only what the form shows. The app still fetches and caches eligibility in full, and doesn't enforce the setting server-side; see the Configuration reference.

Leave Webhook Enabled on the Status Updates tab at its default of true. The webhook you connect in Steps 6 and 7 is how requests get closed.

🚧

Important

Keep the duration selection in sync with Entitle's own settings. In the Entitle admin console, go to Administration > Org Settings > JIT Requests. Entitle doesn't expose these settings through its API, so the app can't synchronize them automatically.

ℹ️

The Configuration form's duration picker renders only in the classic UI16 or Polaris form. Administer this record from the classic UI, not Configurable Workspace.

Step 6: Create the webhook service account (ServiceNow)

The webhook is how requests get closed: Entitle pushes each status change to the app's inbound endpoint, authenticating as this account. Webhook Enabled is already true, but nothing arrives until you complete this step and Step 7. To poll Entitle for status instead of, or in addition to, the webhook, see Enable status polling.

  1. In ServiceNow, go to All > User Administration > Users.
  2. Go to User Administration > Users, and then click New.
  3. Configure the user:
    • User ID: entitle_webhook_user, or your preferred name
    • First name: Entitle
    • Last name: Webhook User
    • Identity Type: Machine
    • Active: checked
  4. Click Submit, then reopen the user record and click Set Password. Record the password securely. You need it in the next step.
  5. On the Roles tab, click Edit and add exactly one role: x_bets_entitle.api. Grant no other roles.

Step 7: Add the webhook (Entitle)

  1. On your workstation, generate the Base64 value for the header from <user>:<password> of the account you created in Step 6. Either command below encodes as UTF-8 with no trailing newline. Replace the two placeholders and copy the output:

    [Convert]::ToBase64String([Text.Encoding]::UTF8.GetBytes('entitle_webhook_user:YOUR_PASSWORD'))
    printf '%s' 'entitle_webhook_user:YOUR_PASSWORD' | base64
  2. In Entitle, go to Org settings > Audit Logs Webhooks and add a webhook with these values:

    • Endpoint URL: https://<instance>.service-now.com/api/x_bets_entitle/entitle_events_api/v1/events
    • Header: {"Authorization": "Basic <value from step 1>"}
  3. Save the webhook.

🚧

Important

If you build the Base64 value another way, use UTF-8 with no trailing newline. PowerShell's default Unicode encoding and bash echo without -n both produce broken credentials; the commands in step 1 avoid both problems. A credential failure produces no application log entry, because platform authentication runs before the app's code. Every failed delivery also counts against Entitle's limit for automatically disabling the webhook, so verify the header value before you save the webhook.

Step 8: Smoke test (ServiceNow)

  1. In ServiceNow, use Service Portal or Employee Center, and then go to BeyondTrust Entitle > Requests.

    Complete these steps as a user who holds x_bets_entitle.requester. Don't use an admin account, and don't impersonate another user.

  2. Open Request Entitle Access. The Resource list offers the resources that user is eligible for in Entitle, limited to the types that Offered Resource Types allows. The first load can take a few seconds while the app fetches eligibility.

  3. Submit a request with a short duration and justification.

  4. Approve it as the manager or as a member of the Default Approval Group.

  5. Watch BeyondTrust Entitle > Requests. The tracking record reaches a terminal state, and the RITM closes with a status comment. With the webhook, this happens within seconds. With the polling flow, it happens on the next due poll.

If the RITM stays open after Entitle shows a decision, see RITM stays open long after Entitle shows a decision. Your basic installation is complete once this test closes the RITM.

Optional setup

Place and brand the catalog item (ServiceNow)

In ServiceNow, go to Service Catalog > Maintain Items > Request Entitle Access.

The item ships in the BeyondTrust Entitle category of the standard Service Catalog so users can find it immediately, but that is just its default home:

  • Move or co-locate it anywhere. The preferred method is to add your own category through the item's Categories related list. That association lives in your scope and never marks the shipped record as customized. You can also edit the item's Category field directly. Routing is unaffected either way: fulfillment follows the item, not its location, so an Entitle item can sit on the same request page as items your own flows fulfill.
  • Rebrand if desired. The item record is intentionally editable: you can rename it and change its short description, description, and icon. The form's fields, Resource, Duration, and Justification, are already brand-neutral.
ℹ️

Direct edits to the shipped item record mark it as customized, so upgrades stop applying vendor updates to that record. Review such records in your upgrade history after each app upgrade.

The item's request experience is designed for Service Portal and Employee Center. In the classic catalog UI, platform-level controls such as quantity, delivery time, and cart may still display. They have no effect on an access request.

Enable status polling (ServiceNow)

  1. In ServiceNow, go to Flow Designer, also called Workflow Studio, and open Status Reconciliation in the BeyondTrust Entitle application.

    Polling is an optional fallback alongside the webhook, or the only status path where your organization doesn't permit inbound webhooks. For how the two paths interact, see Status reconciliation.

  2. Open Status Reconciliation and click Activate. This flow is the one shipped record that is not read-only, so that you can activate it. Don't change anything else in it.

  3. (Optional) Adjust Polling Interval (minutes) and Maximum Polling Age (days) on the Configuration record's Status Updates tab. See Tune polling.

To stop polling, open the flow again and click Deactivate. When you activate the flow, the platform marks it as customized on your instance; see Upgrades.

Customize approvals, validation, or notifications

To replace the built-in approval chain, add pre-submit checks, or notify requesters through another channel (see Customize the application). For example, you can auto-approve in ServiceNow and let Entitle's own workflow approve.

The requester experience

Request Entitle Access presents four fields:

FieldBehavior
ResourceOnly resources the requesting user is currently eligible for in Entitle, limited to the types that the Configuration record's Offered Resource Types allows. The default is bundles and roles. The app caches eligibility per user and refreshes it automatically: in the background when the cache is mildly stale, and synchronously when it is expired or empty.
DurationThe allowed durations for the selected resource. If the resource defines its own allowed durations in Entitle, the form offers those. Otherwise, it uses the fallback list from the Configuration record. The form offers Forever only where it is enabled.
JustificationMandatory free text that the app passes to Entitle and that approvers can see.
On Behalf OfVisible only to holders of x_bets_entitle.proxy_requester. Submits the request for another user, whose manager and eligibility then drive approval and fulfillment.

Notable guardrails:

  • Impersonation is blocked. An impersonating admin sees a warning on the form and can't submit. A server-side rule enforces the same block regardless of client state.
  • One request, one RITM. Each RITM maps to exactly one Entitle request, and the app enforces this server-side.
  • Requesters receive one comment on their RITM when the request is submitted, and one when it closes. The first comment includes the resource, duration, and Entitle reference ID. The second includes the outcome and its reason. The fulfillment flow writes these comments itself. A notification hook can add other channels but doesn't replace them. If your instance's Request Item commented email notification is active, the platform also emails each comment to the requester.

Configuration reference

All application settings live on the single Entitle Configuration record, x_bets_entitle_configuration, named Default. The app deliberately ships no system properties. The record is a singleton, and the app blocks inserting a second row. The app seeds the record on install with the defaults below. Changes take effect immediately, with no cache flush or restart needed.

SettingTabDefaultDescription
NameMainDefaultFixed identifier of the singleton record. Read-only.
Offered Resource TypesMainBundles and RolesWhich resource types the request form's Resource list offers: Bundles and Roles, Bundles only, or Roles only. This is a display filter, not a control. The app still fetches and caches eligibility for every type, and a change applies on the next form load with no cache refresh. If a request for a hidden type arrives another way, such as through REST, an order guide, or a script, the app still accepts it when Entitle says the user is eligible. Entitle remains the authority on what a user may have.
Default Approval GroupMainemptyGroup that the built-in approval chain uses when the requester has no manager. The chain is fail-closed: with no manager and no group, it rejects requests.
CAB Approval GroupMainemptyGroup that approves CAB-escalated requests. Leave it empty to disable CAB escalation.
CAB Escalation Duration (Days)Main0Requests for this many days or longer, or for Forever, require a second approval from the CAB group. 0 disables escalation.
Duration OptionsRequest DurationsNone; select during setupFallback durations that the request form offers when the Entitle resource defines none of its own. You must select at least one before anyone can submit a request. You manage this setting through the checkbox picker, and the app stores it as comma-separated seconds, where -1 means Forever.
Default DurationRequest DurationsNonePre-selected duration on the request form. Must be one of the enabled duration options; the form validates this on save.
Eligibility Soft TTL (minutes)Eligibility Cache60Time to live (TTL): the age at which cached eligibility becomes stale. The app still serves stale eligibility but refreshes it in the background.
Eligibility Hard Expiry (minutes)Eligibility Cache480Age at which cached eligibility becomes unusable. The app refreshes it synchronously before serving the form.
Polling Interval (minutes)Status Updates5Minimum minutes between status polls for each in-flight request. Applies only after you activate the Status Reconciliation flow, which ships inactive. That flow runs every minute, and this field is the only setting you need to tune.
Maximum Polling Age (days)Status Updates7How long polling keeps trying a submitted request that has not reached a final Entitle status. Once a request exceeds this age, the app sets it to failed and closes the RITM as Closed Incomplete with an explanatory comment. A blank value, or a value below 1, uses 7; there is no "never give up" setting. Applies only after you activate the Status Reconciliation flow. See Tune polling.
Webhook EnabledStatus UpdatestrueEnables the inbound events endpoint, which is the primary status path. Requires the webhook service account and the Entitle webhook that you configure in Step 6 and Step 7. While false, the endpoint answers 404.
Approval HookAdvancedemptyYour subflow that replaces the built-in approval chain. See Customize the application.
Pre-Submit Validation HookAdvancedemptyYour subflow that replaces the built-in final validation.
Notification HookAdvancedemptyYour subflow that notifies requesters through another channel, such as email or chat. The built-in hook does nothing; the app writes the RITM comments either way.
Flow OverrideAdvancedemptyYour subflow that replaces the entire fulfillment flow.
Log LevelAdvancedErrorMinimum severity the app writes to the system log: Debug, Info, Warn, or Error. Takes effect immediately. Raise it to Info or Debug only while troubleshooting.

The built-in approval chain

When no Approval Hook is configured, the built-in approval chain runs in this order:

  1. Manager approval on the RITM, by the manager of the target user. The target user is the On Behalf Of user when that field is set, and otherwise the requester.
  2. If no manager resolves, the Default Approval Group approves instead. The two are mutually exclusive, so at most one of them runs.
  3. If the requested duration meets the CAB Escalation Duration threshold, or is Forever, and a CAB Approval Group is set, that group must give a second approval.
  4. If neither a manager nor a Default Approval Group is available, the chain rejects the request.

At most two approval levels apply to any request. Approval is fail-closed throughout: any error path denies rather than allows.

Customize the application

This section is for flow developers.

The application ships with a complete fulfillment flow, and its logic is read-only by design. You extend it through four override points, not by editing app artifacts. Each override point is a reference field on the Configuration record's Advanced tab:

FieldWhat you provideWhat it replaces
Pre-Submit Validation HookSubflowThe built-in final validation before submission to Entitle
Approval HookSubflowThe built-in approval chain: manager, then default group, then CAB
Notification HookSubflowThe built-in hook, which does nothing. The fulfillment flow writes requester comments either way.
Flow OverrideSubflowThe entire Access Request fulfillment flow

When a field is empty, the built-in behavior runs. When a field points at your subflow, a dispatcher invokes it at runtime through Flow Designer's Dynamic Flow flow logic, passing the documented inputs and reading the documented outputs back. The flow engine awaits the Approval and Pre-Submit hooks natively: the calling flow suspends without holding a thread or timing out, so your subflow can take hours or days. That includes waiting on human decisions, such as Ask For Approval, a chat prompt, or an email round-trip. The dispatcher starts the Notification Hook and Flow Override fire-and-forget, without waiting for them.

Requirements common to all overrides

  • Build your override in your own scoped application or in global scope. You can't create records inside the Entitle application's scope.
  • Match the shipped subflow's signature. The built-in Approval Hook, Pre-Submit Validation Hook, and Notification Hook subflows carry the exact input and output contract. For the Flow Override, the contract is the shipped Access Request Override Template. Input and output names, types, and reference tables must match exactly. A misspelled output is the same as no output.
  • Extend rather than replace when you can. Your scope can call the built-in hook subflows. Your custom hook can call the shipped subflow as a step and add logic before, after, or around it. For example, it can run the built-in approval chain and then post the outcome to a chat channel. This is safe by design: the shipped hooks contain no dispatch logic, so recursion is impossible.
  • All four overrides are subflows. The configuration pickers show only active subflows, so you can't select drafts or triggered flows.
  • Set Accessible from: All application scopes on your subflow, and activate and publish it.
  • All context arrives through the inputs. The application's tables are private, and your scope can't read them. Don't design a hook that queries them.
  • The Approval and Pre-Submit Validation hooks run with the privileges of the requesting session. The Notification hook and Flow Override run as system. Writes from your scope to platform tables, such as sc_req_item work notes, may generate Restricted Caller Access requests the first time. An admin approves them once.

Failure modes: know them before you build

Your subflow runs through a Dynamic Flow step, and two failure classes behave differently. The fulfillment flow's normal branches handle a hook that runs but returns a missing or unexpected output. A hook that can't start or throws stops the calling flow with an error. A hook can't start when it is inactive, isn't accessible from all scopes, or has the wrong signature. That error appears in the flow execution record under Workflow Studio > Operations, not as an application log line.

The following table shows how each override behaves in both failure classes:

OverrideRuns, but output missing or unexpectedCan't start, or throws
Pre-Submit Validation Hookpassed = false rejects. Always assign passed explicitly on every path, and don't rely on an unset value.The fulfillment flow stops with an error and leaves the RITM open.
Approval HookAnything other than exactly approved, including no value, rejects the request. The RITM closes as Closed Incomplete with your failure_reason as the comment. If you didn't set one, the comment is Your Entitle access request was closed without access being granted.The fulfillment flow stops with an error and leaves the RITM open.
Notification HookHas no outputs.Started fire-and-forget: a failure shows in your subflow's own execution and doesn't affect the request.
Flow OverrideHas no outputs.The fulfillment flow stops with an error and leaves the RITM open.
⚠️

Important

A broken Approval Hook never approves, and it doesn't fall back to the built-in chain. A hook that runs but returns anything other than approved rejects the request. A hook that can't start or throws halts fulfillment and leaves the RITM open for an administrator to close. Return approval_result on every path, with a requester-appropriate failure_reason on denials, and test the hook as a normal requester before go-live.

Approval Hook

Replace the built-in approval chain. For example, delegate approval to an external IT service management (ITSM) or governance, risk, and compliance (GRC) system, use a different approval matrix, or apply auto-approval rules. Your hook bypasses the platform approval engine completely: ServiceNow creates no sysapproval_approver records unless your subflow creates them. You can use Ask For Approval inside your hook.

Inputs

The Approval Hook receives these inputs:

NameTypeMandatorySemantics
requested_itemReference → sc_req_itemYesThe RITM being fulfilled
requesting_userRecord(s) → sys_userYesThe user who needs the access
on_behalf_ofRecord(s) → sys_userSet when a proxy requester submitted for someone else
duration_secondsIntegerYesRequested duration in seconds; -1 means Forever
resource_display_nameStringYesHuman-readable resource name, for approval messages

Outputs

The Approval Hook returns these outputs:

NameTypeSemantics
approval_resultStringReturn exactly approved, in lowercase, to allow. Any other value denies; use rejected by convention. The hook is fail-closed: an empty or missing value counts as rejected.
failure_reasonStringReturn with any denial. The app shows it verbatim to the requester in the RITM closure comment, so write it for end users.

On a non-approved result, the app closes the RITM as Closed Incomplete with your failure_reason, and the Notification Hook fires with terminal_state = rejected.

Long-running approvals are supported: the flow engine waits for your subflow however long it takes. However, a hook that never completes leaves the request waiting indefinitely. If your organization needs a timeout, build your own, for example a Wait for a duration step that races the approval and then returns rejected.

Recipe: Minimal auto-approve for the Entitle-managed model. If Entitle governs approvals entirely and ServiceNow doesn't need to add a second approval layer, the whole hook is one step:

  1. Create a subflow with the Approval Hook's inputs and outputs. Copy the signature from the shipped Approval Hook subflow.
  2. Add a single Assign Subflow Outputs step: approval_result = approved.
  3. Publish the subflow with access from all scopes, and set it as the Approval Hook in the configuration.

Every request then passes straight to Entitle, where Entitle's own workflow performs the real approval.

Recipe: Extend rather than replace. Create your subflow with the same signature, and call the shipped Approval Hook subflow as its first step. The shipped subflow is public and embeddable. Map your inputs through, and then add your extra behavior, such as posting the outcome to Teams or Slack. Finally, assign the shipped hook's outputs to your own outputs.

Pre-Submit Validation Hook

This hook is the final check immediately before submission to Entitle. Use it to add organizational checks such as change freezes, risk scoring, or configuration management database (CMDB) lookups. What you give up is the built-in validation, which re-confirms eligibility and checks that the duration is in the allowed list. If your hook doesn't re-implement equivalent checks, they don't happen. Note the sequencing: approval runs before pre-submit validation.

Inputs: All of these inputs are mandatory: requested_item (Reference → sc_req_item), resource_sysid (String), resource_id (String), resource_type (String), duration_seconds (Integer, where -1 means Forever), and justification (String). The resource_id value is the Entitle resource's globally unique identifier (GUID).

Outputs

The Pre-Submit Validation Hook returns these outputs:

NameTypeSemantics
passedTrue/Falsefalse rejects the request; true lets it proceed. Assign it on every path; an unset value is not a documented outcome.
failure_reasonStringShown verbatim to the requester in the RITM closure comment.

When passed = false, the app closes the RITM as Closed Incomplete with Request rejected by pre-submit validation: <failure_reason>, the Notification Hook fires with terminal_state = validation_failed, and the app sends nothing to Entitle.

Recipe: Change-freeze gate. In your subflow, look up your freeze calendar. Inside a freeze window, assign passed = false and failure_reason = "Access requests are paused during the change freeze (until <date>)." Otherwise, assign passed = true. To keep the built-in eligibility and duration checks as well, call the shipped Pre-Submit Validation Hook subflow first, and combine its result with yours using AND.

Notification Hook

Notify requesters through another channel, such as Teams, Slack, or email, at each transition. The built-in hook does nothing. The fulfillment flow itself writes one RITM comment at submission and one at closure, independent of this hook. An override therefore adds a channel and never has to re-create or suppress those comments. The dispatcher starts the hook fire-and-forget: it has no outputs, the fulfillment flow doesn't wait for it, and a failure inside it shows only in your subflow's own execution record.

Inputs: requested_item (Reference → sc_req_item), terminal_state (String, using the values in the table below), entitle_request_id (String, once one exists), and failure_reason (String, populated for failure-type states).

The following table lists each terminal_state value:

terminal_stateFired whenRITM comment the flow writes
submittedSuccessfully submitted to EntitleAccess request submitted to Entitle (ID: <id>). Awaiting confirmation. followed by Requested: <resource> for <duration>
approvedNot fired in this release. Entitle's approved status counts as in-flight, and the app waits for granted. The value is retained so custom hooks built against it keep working.None
provisionedEntitle reports access granted, or granted and since endedAccess provisioned successfully. or Access was provisioned and has since been revoked in Entitle.
rejectedApproval denied, resource no longer eligible at fulfillment time, or Entitle rejected the requestYour approval failure_reason; You are no longer eligible for the requested resource.; or Access request rejected by Entitle.
validation_failedPre-submit validation rejected the requestRequest rejected by pre-submit validation: <failure_reason>
failedSubmission or provisioning failed, or polling gave up after the Maximum Polling AgeThe failure reason, or Access request failed in Entitle. when Entitle reports the failure without one
expiredEntitle reports the request expiredAccess request expired in Entitle.
cancelledThe requester withdrew the request in Entitle before a decisionAccess request was cancelled in Entitle.

Two closures don't fire the hook: the flow stopping because no Configuration record exists, and the flow's catch-all error handler. Both still write a closure comment.

Recipe: Chat notifications. Create a subflow with the signature above. Branch on terminal_state, and call your Teams or Slack spoke with a message built from the inputs. The flow writes the RITM comments regardless, so you don't need to call anything to keep them.

Flow Override

Replace the entire fulfillment flow. Use this alternative when your organization's request lifecycle differs fundamentally. When the field is set, the shipped flow updates the RITM short description and description, starts your subflow fire-and-forget, and ends. None of the built-in behavior runs: no eligibility validation, no approval, no hooks, no Entitle submission, no tracking record, no notifications, and no RITM closure.

Contract: A single input, requested_item (Reference → sc_req_item), and no outputs.

Build your override by copying the shipped Access Request Override Template subflow, which declares the input and restates the obligations. At minimum, a conforming replacement must:

  1. Validate the request. The app does not re-check eligibility for you.
  2. Perform whatever approval your organization requires.
  3. Submit to Entitle. The Spoke's actions are the supported integration surface.
  4. Track status through to a terminal state.
  5. Close the RITM on every path, including failures. Otherwise, requests hang open.

Clone the catalog item

As an alternative to the Flow Override, you can duplicate the Request Entitle Access item and point the copy's Flow field at your own flow. The shipped flow and all hooks never run for your item. However, you also take ownership of the catalog experience, including the eligibility-driven resource picker, duration options, freshness checks, and the impersonation guard. Prefer the Flow Override when you want to keep the shipped item and user experience and replace only fulfillment. Clone the item only when the request form itself must change.

Configure and verify an override

  1. Go to BeyondTrust Entitle > Configuration, and open the Advanced tab.
  2. Set the relevant field to your subflow and save.
  3. Submit a test request and verify the divert:
    • Flow executions: Under Workflow Studio > Operations, the relevant dispatcher subflow shows the override branch, and your subflow appears as its own child execution.
    • RITM activity stream: Your hook's effects appear, and the corresponding default messages don't.
    • Flow execution errors: A hook that couldn't start or threw shows as an error on the dispatcher's Dynamic Flow step. Check that your subflow is activated, accessible from all scopes, and matches the shipped signature.

To return to built-in behavior, clear the field. The app reads the configuration on each execution.

Use the following table to diagnose an override that isn't working:

SymptomLikely cause
The dispatcher's Dynamic Flow step errors and the RITM stays openThe subflow was deactivated after selection, isn't set to Accessible from: All application scopes, has a signature mismatch, or has an unhandled error inside it
Every request is rejected, and the closure comment reads Your Entitle access request was closed without access being granted.The approval subflow returns no approval_result, or a value other than exactly approved, and no failure_reason. Assign both outputs on every path.
The RITM closed with Request rejected by pre-submit validation: and no reasonpassed = false without a failure_reason
Your hook's record updates don't applyA Restricted Caller Access request is waiting for admin approval
Requests hang open with Flow Override setYour subflow must close the RITM on every path

Operations and maintenance

Status reconciliation: how requests get closed

Two mechanisms can drive a submitted request to closure. They share the same terminal-state machinery and are safe to run together:

  • Webhook: default, push-based. Entitle streams audit events to the app's inbound endpoint, and the app filters for whole-request status changes and applies them immediately. This is the primary path: Webhook Enabled ships as true. Once you configure the service account and the Entitle webhook in Step 6 and Step 7, granted, rejected, and cancelled outcomes close the RITM within seconds.
  • Polling: optional, opt-in. The Status Reconciliation scheduled flow ships inactive; see Enable status polling. When activated, it runs every minute and polls each in-flight request against Entitle. However, it polls each individual request at most once per Polling Interval, which defaults to 5 minutes. Because it is a high-frequency job, tune the rate only by editing the configuration field, and never modify the flow trigger. Use polling as a fallback alongside the webhook, or as the only path where your organization doesn't permit inbound webhooks.

Track in-flight and historical requests under BeyondTrust Entitle > Requests. The states are external, meaning submitted and awaiting Entitle, and the terminal states provisioned, rejected, failed, expired, and cancelled. When a request reaches a terminal state, the app closes the RITM, and the reason becomes the requester's closure comment.

The parent Request closes through the platform's standard roll-up when its last requested item closes. It closes as Closed Complete, or as Closed Incomplete if the item did not complete. A Request that also holds other items, for example several ordered through one cart, stays open until those finish too. To drive that roll-up, the app sets the RITM's Stage field to complete or closed_incomplete at closure, and doesn't touch Stage anywhere else. Any intermediate stages remain part of your process. Because the app defines no stage labels, the Stage field shows these raw values.

Webhook behavior and monitoring

Endpoint: POST https://<instance>.service-now.com/api/x_bets_entitle/entitle_events_api/v1/events

Authentication is standard ServiceNow Basic authentication, enforced by the platform. The endpoint's access control list (ACL) requires the x_bets_entitle.api role, and the handler itself contains no credential logic. For initial configuration, see Step 6 and Step 7.

  • The platform rejects failed authentication before the app runs, so bad credentials produce no application log line. Diagnose them from the platform's authentication logs.
  • Entitle automatically disables a webhook after repeated delivery failures: approximately a dozen non-2xx responses within a couple of hours. The endpoint deliberately answers 200 to everything it can, including malformed payloads, irrelevant events, unknown request IDs, and even its own handler errors. As a result, only real authentication failures or the 404 feature gate count toward that limit. If deliveries stop, check Entitle's webhook status first.
  • You can disable the webhook at any time by setting the configuration field to false, but only if you have activated polling. With neither path active, in-flight requests stay external and RITMs stay open.

Tune polling

  • Polling applies only if you have activated the Status Reconciliation flow. With the webhook alone, nothing polls.
  • Polling Interval is a per-request minimum, so if you lower it, API traffic increases roughly in proportion to your number of concurrent in-flight requests. The default of 5 minutes suits most volumes. If you run polling alongside the webhook and want to minimize API calls, raise it.
  • The app logs poll failures and fails open: it retries the record on the next due cycle, up to the Maximum Polling Age.
  • Maximum Polling Age, which defaults to 7 days, limits how long the app polls any one request. If a request has no final Entitle status by then, the app closes it as failed, closes its RITM as Closed Incomplete with an explanatory comment to the requester, and logs an error. This typically happens because of an Entitle status the app doesn't recognize, or an Entitle API error that never clears. The app does not notify Entitle, so if Entitle later approves the request, the user gets access while the RITM stays closed. If your Entitle approvals legitimately take longer than a week, raise the value.

Credential rotation

Both credentials are record-level edits, with no code or flow changes:

  • Entitle API token: Update it in Entitle first, and then in ServiceNow. Before the current token expires, create a replacement API token in Entitle under Org settings > Tokens. Then open the API Key credential from Step 3 under All > Connections & Credentials > Credentials, replace the API Key, and save. Once the new token is working, Revoke the old token in Entitle.
  • Webhook service account password: Update it in ServiceNow first, and then in Entitle. Change the service account's password, and then update the Entitle webhook header with the new Base64 value, using the same procedure as Step 7.

Scheduled jobs

The app uses two scheduled jobs:

JobSchedulePurpose
Status Reconciliation scheduled flowEvery 1 minute when activated; ships inactiveOptional job that polls in-flight requests. Polling Interval governs the per-request cadence, and the app stops polling a request after Maximum Polling Age. Because the job is high-frequency, tune it only through these fields, never by editing the trigger.
Purge Expired Entitle EligibilityDaily at 10:00Deletes expired eligibility cache rows.

Logs and diagnostics

The app writes level-gated messages to the system log, syslog.list, with source prefixes of the form [Entitle:<Component>]. The hook dispatch path also writes [Entitle] and [Entitle Flow] warnings. Set Log Level on the Configuration record. It ships as Error, which is right for normal operation. Raise it to Info or Debug while troubleshooting, and set it back afterward. Changes take effect immediately. Application-scoped entries also appear under System Logs > Application Logs, filtered to BeyondTrust Entitle.

Upgrades

If you edited any shipped record directly, for example by renaming the catalog item, the platform marks those records as customized and skips them during app upgrades. After each upgrade, review the skipped records in the upgrade history, and deliberately re-apply or revert your changes. Overrides you configure through the hook fields are unaffected by upgrades, because they live in your scope.

ℹ️

When you activate the Status Reconciliation flow, that counts as a customization of that one record. After each upgrade, check that the flow is still active if you rely on polling, and review it in the skipped-records list. Its content rarely changes, so accepting your version is normally the right choice.

Troubleshooting

Resource list on the request form is empty

Symptoms: The Resource field offers no options, or the form shows an eligibility error.

Possible causes and solutions:

  • The user has no JIT-eligible resources in Entitle. Verify their eligibility in the Entitle admin console.
  • The Entitle API call failed. Check syslog for [Entitle:*] errors, and verify the alias URL and token. See the error code reference below.
  • Offered Resource Types hides every type the user is eligible for. For example, the user is eligible only for roles, and the setting is Bundles only. The cache is fine, so a refresh doesn't help. Change the setting, or grant the user a resource of an offered type in Entitle.
The request form loads slowly for a user

Symptoms: A noticeable delay before the Resource list populates.

Possible causes and solutions: A first load or a hard-expired cache triggers a synchronous eligibility fetch from Entitle. Later loads come from the cache. No action is needed unless it happens on every load. If it does, check the Eligibility Soft TTL and Eligibility Hard Expiry settings on the Configuration record.

Every request is rejected immediately

Symptoms: RITMs close as Closed Incomplete moments after submission, before any approval.

Possible causes and solutions:

  • No manager resolves for the target user, and no Default Approval Group is set. The built-in chain is fail-closed. Set a Default Approval Group.
  • A configured Approval Hook is broken. See Configure and verify an override.
RITM stays open long after Entitle shows a decision

Symptoms: The Entitle console shows granted or rejected, but the ServiceNow request record remains external, and the RITM stays open.

Possible causes and solutions:

  • The webhook isn't delivering. In Entitle, verify the webhook, which Entitle may have disabled automatically after delivery failures. Also verify the service account credentials, and confirm that Webhook Enabled is true. See Webhook deliveries are failing.
  • You rely on polling, but the Status Reconciliation flow isn't active; it ships inactive. The Maximum Polling Age applies only while polling is active. On a webhook-only installation, a request whose final webhook event never arrives stays open until you close it.
  • The polling interval is set very high. Check Polling Interval on the Configuration record.
  • Poll or handler errors occurred. Temporarily set Log Level to Info, and check the application log for [Entitle:*] entries. The app writes an unrecognized Entitle status to the request record's Error Message field and keeps polling until the Maximum Polling Age closes the request. See RITM closed Closed Incomplete: no final status.
Webhook deliveries are failing

Symptoms: Entitle reports delivery failures, or has automatically disabled the webhook.

Possible causes and solutions:

  • 401 or 403: The service account credentials are wrong or expired, or the account lacks x_bets_entitle.api. Diagnose from the platform authentication logs, because the app logs nothing for authentication failures.
  • 404: Webhook Enabled is false on the Configuration record.
RITM closed _Closed Incomplete_ with a validation message

Symptoms: The closure comment reads Request rejected by pre-submit validation: ….

Possible causes and solutions: Pre-submit validation, either built-in or from a custom hook, rejected the request. The comment carries the reason. If a custom hook is configured, your organization authors its failure_reason.

RITM closed Closed Incomplete: no final status from Entitle

Symptoms: The closure comment reads No final status was received from Entitle within N days of submission, so this request is no longer being tracked. …, and the request record's State is failed.

Possible causes and solutions: Polling gave up after the Maximum Polling Age. The system log, syslog.list, has an error-level entry that begins with Gave up polling Entitle request. Its Last recorded error: value shows what the app last saw: usually an Entitle status it doesn't recognize, or an Entitle API error that never cleared.

  1. Check the request in Entitle. It may still be pending there. If Entitle later approves it, the requester receives access even though the RITM stays closed.
  2. If your Entitle approvals routinely take longer than the limit, raise Maximum Polling Age (days) on the Configuration record.
  3. If the log shows an unrecognized Entitle status, report it to BeyondTrust support so that BeyondTrust can map it.

Entitle API error codes

The Spoke returns these codes, and the app logs them. Use them as stable values to branch or search on:

CodeMeaning
auth_error401 or 403. The API token is invalid or was rotated.
not_found404
conflict409
validation_error422, or missing local configuration
rate_limited429
upstream_error5xx from Entitle
client_errorOther 4xx
connection_errorNetwork or firewall problem on the path to the Entitle API host

Security considerations

  • Credentials: The Entitle API token is an organization-level administrator credential. The API Key credential attached to the Spoke's connection alias stores it encrypted. Give the token an expiration in Entitle, and rotate it on your normal schedule. The webhook uses a dedicated service account with a single-purpose role, x_bets_entitle.api, that grants no table access. The endpoint is POST-only, requires authentication, and answers 404 while Webhook Enabled is false.

  • Access control: The app's tables are private to its scope; end users interact only through the catalog item. Administration requires x_bets_entitle.admin. User criteria restrict the catalog item to x_bets_entitle.requester.

  • Application integrity: App logic is read-only on installing instances. Customers and support can read the code, but extend it only through the hook contracts, never by editing app internals.

  • Impersonation guard: You can't submit access requests while impersonating another user. The app enforces this on both the client side and the server side.

  • Data stored in ServiceNow: The app maintains four private tables:

    • The singleton configuration
    • A per-user eligibility cache of resource names and IDs that a user may request, refreshed from Entitle and purged after expiry
    • An internal catalog of Entitle resources, meaning roles and bundles
    • One request tracking row per submitted access request, holding the Entitle request ID, state, timestamps, and error messages

    The app writes requester-visible status as comments on the RITM.

  • To view the App Privacy Policy page, go to BeyondTrust Entitle > App Privacy Policy. It describes data collection, use, sharing, and retention. The Help page summarizes configuration, roles, and troubleshooting inside the instance.

Best practices

  • Set a Default Approval Group before go-live. It is the fallback for every user without a manager, and the built-in chain rejects requests when neither is available.
  • Keep Duration Options aligned with Entitle whenever either side changes. There is no automatic sync. In Entitle, the settings are under Administration > Org Settings > JIT Requests.
  • Connect the webhook before go-live. It is the default status path, and nothing closes a request without it. If you want a fallback for missed deliveries, or can't accept inbound webhooks, also activate the optional Status Reconciliation polling flow.
  • Extend hooks rather than replace them where possible. When your custom hook calls the shipped subflow, the built-in behavior and your additions stay in one place.
  • Test overrides as a normal requester, not as an admin. Privilege differences can mask access problems in custom hooks.
  • Review upgrade-skipped records after each app upgrade if you have edited any shipped record, such as a renamed catalog item.
  • Rotate the Entitle API token and webhook service-account password on your organization's normal credential schedule. For steps, see Credential rotation.

Additional resources


Did this page help you?

©2003-2026 BeyondTrust Corporation. All Rights Reserved. Other trademarks identified on this page are owned by their respective owners. BeyondTrust is not a chartered bank or trust company, or depository institution. It is not authorized to accept deposits or trust accounts and is not licensed or regulated by any state or federal banking authority.