---
title: Scripting API
description: AM provides the following functionality and artifacts for scripting:
component: pingam
version: 7.2
page_id: pingam:scripting-guide:scripting-api
canonical_url: https://docs.pingidentity.com/pingam/8.1/am-scripting/scripting-api.html
llms_txt: https://docs.pingidentity.com/pingam/llms.txt
docs_for_agents: https://developer.pingidentity.com/build-with-ai/docs-for-agents.md
superseded_by: https://docs.pingidentity.com/pingam/8.1/am-scripting/scripting-api.html
section_ids:
  property-substitution-scripts: Reference substituted properties in scripts
  example_property_value_resolution_in_a_scripted_decision_node: "Example: Property value resolution in a scripted decision node"
  esvs-in-scripts: Reference ESVs in scripts
---

# Scripting API

AM provides the following functionality and artifacts for scripting:

* [Scripted module API](../authentication-guide/scripting-api-authn.html)

  (*Authentication chains only*)

  Access authentication state data, user profile data, request data, and information gathered by client-side scripts.

* [Scripted decision node API](../authentication-guide/scripting-api-node.html)

  (*Authentication trees only*)

  Access data in request headers, shared state, and user session data.

* [Policy Condition Script API](../authorization-guide/scripted-policy-condition.html#scripting-api-policy)

  Access the authorization state data, the information pertaining a session, and the user's profile data in authorization policies.

* [Customize OAuth 2.0 with plugins](../oauth2-guide/customizing-oauth2-scopes.html)

  Extend authorization server behavior with the OAuth 2.0 plugins:

  * **[Access token modification plugin](../oauth2-guide/modifying-access-tokens-scripts.html)** Modify the key-value pairs contained within an OAuth 2.0 access token.

  * **[Authorize endpoint data provider plugin](../oauth2-guide/plugins-auth-endpoint-data-provider.html)** Return additional data from an authorization request.

  * **[Scope evaluator plugin](../oauth2-guide/plugins-scope-evaluator.html)** Evaluate and return an OAuth2 access token's scope information.

  * **[Scope validator plugin](../oauth2-guide/plugins-scope-validator.html)** Customize the set of requested scopes for authorize, access token, refresh token and back channel authorize requests.

  * **[User info claims plugin](../oauth2-guide/plugins-user-info-claims.html)** Map scopes to claims and data for OpenID Connect ID tokens.

* [Token exchange scripting API](../oauth2-guide/scripting-api-may_act.html)

  Add the `may_act` claim when performing OAuth 2.0 token exchange.

* [Accessing HTTP Services](scripting-api-global-http-client.html)

  Configure the parameters for the HTTP client object in any server-side script.

* [Debug logging](scripting-api-global-logger.html)

  Add debug logging to any server-side script.

* [Configuring AM for token exchange](../oauth2-guide/token-exchange-configuration.html)

  Add `may_act` claims to OAuth 2.0/OpenID Connect exchanged tokens.

## Reference substituted properties in scripts

The `systemEnv` binding, available to all AM script types, includes an instance of the `ScriptPropertyResolver` class. This interface exposes the following methods:

* JavaScript

* Groovy

```javascript
String getProperty(String propertyName);
String getProperty(String propertyName, String defaultValue);
```

where:

* `propertyName` is the [configuration expression](../setup-guide/property-value-substitution.html#configuration-expressions) (without the ampersand braces)

* `defaultValue` is the default value set for that property in the configuration expression

```groovy
String getProperty(String propertyName);
String getProperty(String propertyName, String defaultValue);
T getProperty(String propertyName, String defaultValue, Class<T> returnType);
```

where:

* `propertyName` is the [configuration expression](../setup-guide/property-value-substitution.html#configuration-expressions) (without the ampersand braces)

* `defaultValue` is the default value set for that property in the configuration expression

* `T` is the data type into which the value should be transformed; one of the following types:

  * `String`

  * `Integer`

  * `Double`

  * `List`

  * `Map`

  * `Boolean`

To reference a substituted property in a script, the property name *must* include a specific prefix. This prefix decreases the risk that random property values are resolved in scripts. Because property value substitution is often used to change secrets, you must be intentional about which properties you want to be able to resolve in scripts. The default prefix, for all script types, is `script`. You can change this prefix in the script type configuration. Select Configure > Global Services > Scripting > Secondary Configurations > *Script Type* > Secondary Configurations > Engine Configuration > Property Name Prefix.

### Example: Property value resolution in a scripted decision node

These examples assume that the property name prefix `script` has been set in the script engine configuration for this script type. The scripts are used in a scripted decision node to get the values of the user's `email`, `hostname`, `port`, and so on. The scripts also show type transformation where the type is not a string.

* JavaScript

* Groovy

```javascript
// Properties should get resolved (set in AM)
var email = systemEnv.getProperty('script.tree.decision.node.email');
var name = systemEnv.getProperty('script.tree.decision.node.hostname', 'defaultHostname');
var port = systemEnv.getProperty('script.tree.decision.node.port', '587', java.lang.Integer);
var double = systemEnv.getProperty('script.tree.decision.node.double, '2.0', java.lang.Double);
var hasPort = systemEnv.getProperty('script.tree.decision.node.hasPort', 'false', java.lang.Boolean);
var map = systemEnv.getProperty('script.tree.decision.node.map', '{"defaultKey":"defaultValue"}', java.util.Map);
var list = systemEnv.getProperty('script.tree.decision.node.list', 'defaultValue', java.util.List);

// Properties should get resolved to their defaults (not set in AM)
var defaultName = systemEnv.getProperty('script.tree.decision.node.hostname.unresolved', 'defaultHostname');
var defaultPort = systemEnv.getProperty('script.tree.decision.node.port.unresolved', '587', java.lang.Integer);
var defaultDouble = systemEnv.getProperty('script.tree.decision.node.double.unresolved', '2.0', java.lang.Double);
var defaultHasPort = systemEnv.getProperty('script.tree.decision.node.hasPort.unresolved', 'false', java.lang.Boolean);
var defaultMap = systemEnv.getProperty('script.tree.decision.node.map.unresolved', '{"defaultKey":"defaultValue"}', java.util.Map);
var defaultList = systemEnv.getProperty('script.tree.decision.node.list.unresolved', 'defaultFirstValue,defaultSecondValue', java.util.List);

// Assert all property values - set the appropriate outcome
if (email === 'test@example.com' && name === 'testHostname' && port === 25 && double === 1.0 && hasPort === true
    && map.get('testKey') == 'testValue' && list == '[testFirstValue, testSecondValue]'
    && defaultName === 'defaultHostname' && defaultPort === 587 && defaultDouble === 2.0 && defaultHasPort === false
    && defaultMap.get('defaultKey') == 'defaultValue' && defaultList == '[defaultFirstValue, defaultSecondValue]') {
outcome = 'true';
} else {
outcome = 'false';
}
```

```groovy
// Properties should get resolved (set in AM)
String email = systemEnv.getProperty('script.tree.decision.node.email');
String name = systemEnv.getProperty('script.tree.decision.node.hostname', 'defaultHostname');
Integer port = systemEnv.getProperty('script.tree.decision.node.port', '587', java.lang.Integer);
Double testDouble = systemEnv.getProperty('script.tree.decision.node.double', '2.0', java.lang.Double);
Boolean hasPort = systemEnv.getProperty('script.tree.decision.node.hasPort', 'false', java.lang.Boolean);
Map map = systemEnv.getProperty('script.tree.decision.node.map', '{\"defaultKey\":\"defaultValue\"}', java.util.Map);
List list = systemEnv.getProperty('script.tree.decision.node.list', 'defaultValue', java.util.List);

// Properties should get resolved to their defaults (not set in AM)
String defaultName = systemEnv.getProperty('script.tree.decision.node.hostname.unresolved', 'defaultHostname');
Integer defaultPort = systemEnv.getProperty('script.tree.decision.node.port.unresolved', '587', java.lang.Integer);
Double defaultDouble = systemEnv.getProperty('script.tree.decision.node.double.unresolved', '2.0', java.lang.Double);
Boolean defaultHasPort = systemEnv.getProperty('script.tree.decision.node.hasPort.unresolved', 'false', java.lang.Boolean);
Map defaultMap = systemEnv.getProperty('script.tree.decision.node.map.unresolved', '{\"defaultKey\":\"defaultValue\"}', java.util.Map);
List defaultList = systemEnv.getProperty('script.tree.decision.node.list.unresolved', 'defaultFirstValue,defaultSecondValue', java.util.List);

// Assert all property values - set the appropriate outcome
if (email.equals('test@example.com') && name.equals('testHostname') && port == 25 && testDouble == 1.0d && hasPort == true
    && defaultName.equals('defaultHostname') && defaultPort == 587 && defaultDouble == 2.0d && defaultHasPort == false
    && map.get('testKey').equals('testValue')
    && list.get(0).equals('testFirstValue') && list.get(1).equals('testSecondValue')
    && defaultMap.get('defaultKey').equals('defaultValue')
    && defaultList.get(0).equals('defaultFirstValue') && defaultList.get(1).equals('defaultSecondValue')) {

    outcome = 'true';
} else {
    outcome = 'false';
}
```

### Reference ESVs in scripts

Use the `esv` prefix to reference ESVs *(tooltip: environment secrets and variables)* from scripts. This prefix lets you create generic scripts that can be customized in different environments. For example:

```javascript
var host = systemEnv.getProperty(esv.my.host);
```
