> For the complete documentation index, see [llms.txt](https://docs.veza.com/4yItIzMvkpAvMVFAamTf/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.veza.com/4yItIzMvkpAvMVFAamTf/features/lifecycle-management/policies-workflows/actions/send-rest-request.md).

# Send REST Payload

Make HTTP requests to external APIs and services as part of provisioning workflows.

Makes HTTP requests to external APIs and services as part of provisioning workflows. This action enables integration with custom applications, webhooks, and REST-based services that support identity management operations.

**Example Use Cases:**

* Notify external systems when users are created or updated in target systems
* Trigger custom provisioning workflows in third-party applications
* Send identity data to SCIM endpoints for user synchronization
* Create service desk tickets for manual provisioning steps
* Execute webhooks to coordinate multi-system workflows
* Extract response data (like user IDs) from external systems for use in downstream actions

| Setting                                         | Description                                                                                                                                                                                                                                                                                                                                                                                                                           |
| ----------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| URL                                             | Target REST endpoint URL. Supports variable substitution using `{attribute_name}` syntax in URL path and query parameters                                                                                                                                                                                                                                                                                                             |
| HTTP Method                                     | Request method: GET, POST, PUT, PATCH, DELETE, HEAD, or OPTIONS. Methods are case-insensitive and automatically converted to uppercase. POST, PUT, and PATCH require a JSON payload                                                                                                                                                                                                                                                   |
| Authorization Header (Legacy)                   | Deprecated inline authentication header (e.g., `Bearer <token>`, `X-API-Key: <key>`). Appears only on actions that already have one. Use **Auth Credentials** instead. See [Inline authorization header](#inline-authorization-header)                                                                                                                                                                                                |
| Auth Credentials                                | Stored REST authentication credential. Required unless the action already has a legacy authorization header. Supplies the authentication header, and a default URL and HTTP method when this action sets neither. For endpoints that don't require authentication, select a credential of type **None**. See [REST Auth Credentials](/4yItIzMvkpAvMVFAamTf/features/lifecycle-management/policies-workflows/rest-auth-credentials.md) |
| JSON Payload                                    | Request body in JSON format. Supports [transformer syntax](/4yItIzMvkpAvMVFAamTf/features/lifecycle-management/transformers.md) for attribute substitution: `{"user": "{name}", "email": "{email}"}`                                                                                                                                                                                                                                  |
| Timeout in seconds                              | Maximum wait time in seconds for the request to complete (default: 60 seconds)                                                                                                                                                                                                                                                                                                                                                        |
| Only send if prior actions resulted in a change | When enabled, the request is only executed if a previous action in the workflow modified or created resources                                                                                                                                                                                                                                                                                                                         |
| Add response to output entities                 | Extract entity data from the API response to make available for downstream actions                                                                                                                                                                                                                                                                                                                                                    |
| Output Entity Type                              | Type of entity to create from response (required if **Add response to output entities** is enabled)                                                                                                                                                                                                                                                                                                                                   |
| Response Entity Attribute                       | JSON path to extract from response using dot notation (e.g., `result` extracts `response.result`, `data.user` extracts `response.data.user`)                                                                                                                                                                                                                                                                                          |
| Response ID Attribute                           | Attribute name containing the entity identifier in the response (defaults to `id`)                                                                                                                                                                                                                                                                                                                                                    |
| Response Name Attribute                         | Attribute name containing the entity display name in the response (defaults to `name`)                                                                                                                                                                                                                                                                                                                                                |

## Variable Substitution

When constructing the webhook URL and JSON payload, you can reference identity attributes using curly brace syntax. Two sources of attributes are available specifically for this URL and payload context:

* **Source-of-identity (SOI) attributes**: Attributes from the identity source triggering the workflow (e.g., Workday worker fields, Okta user attributes).
* **Sync Identities output entity attributes**: When a Sync Identities action precedes this action in the same workflow, attributes from the provisioned or updated target user (such as Active Directory user attributes) are also available. See [Standard Active Directory attributes available for substitution](#standard-active-directory-attributes-available-for-substitution) below.
* **Generated password (Early Access)**: When a [Sync Identities](/4yItIzMvkpAvMVFAamTf/features/lifecycle-management/policies-workflows/actions/sync-identities.md) or [Reset Password](/4yItIzMvkpAvMVFAamTf/features/lifecycle-management/policies-workflows/actions/reset-password.md) action precedes this action and password output is enabled, the generated password is available as `{EntityType.password}`. See [Password output (Early Access)](#password-output-early-access) below.

```
URL: https://api.example.com/users/{email}/provision?dept={department}
Payload: {"name": "{first_name} {last_name}", "role": "{job_title | UPPER}"}
```

Available transformations include `UPPER`, `LOWER`, `TRIM`, and accessing nested attributes with dot notation, such as `{Manager.email}`. See [Transformers](/4yItIzMvkpAvMVFAamTf/features/lifecycle-management/transformers.md) for complete transformation syntax.

> **Note**: If any placeholder in the URL or payload cannot be resolved (e.g., due to missing attributes), the entire transformation is skipped and the original URL is used without any substitution. The system logs a warning for troubleshooting. Ensure all referenced attributes exist in the source of identity to enable proper variable substitution.

## Form field substitution (Access Requests only)

When a Send REST Payload action is configured as part of an Access Request [catalog definition](/4yItIzMvkpAvMVFAamTf/features/access-hub/configuration.md#creating-a-send-rest-payload-catalog-definition), the JSON payload can reference form field values submitted by the requester. This enables dynamic payloads where the requester provides values (such as a role name or resource ID) at request time, and those values are injected into the API call.

Use the `{$form_field.field_name}` syntax in the JSON payload, where `field_name` matches a field defined in the catalog definition's form fields.

To configure form field substitution:

1. Create a Send REST Payload action in a provisioning policy with placeholders in the JSON payload:

   ```json
   {"roleName": "{$form_field.role_name}", "roleId": "{$form_field.role_id}"}
   ```
2. Create a Send REST Payload [catalog definition](/4yItIzMvkpAvMVFAamTf/features/access-hub/configuration.md#creating-a-send-rest-payload-catalog-definition) and add form fields with names that match the placeholders (e.g., `role_name`, `role_id`).
3. When a user submits an access request using this catalog definition, they complete the form fields. The submitted values replace the corresponding `{$form_field.*}` placeholders in the payload before the REST call is made.

Form field substitution applies to the JSON payload only. It does not apply to the webhook URL or authorization header. Each placeholder must sit inside a JSON string literal (between two `"` characters), as in `"roleName": "{$form_field.role_name}"`. Placeholders outside string context are left untouched so the resulting JSON fails to parse at execution time rather than silently emitting malformed JSON.

Substituted form-field values are JSON-encoded automatically. Quotes, backslashes, and control characters in the submitted value are escaped, so a value such as `alice"bob` is emitted as `alice\"bob` and cannot break out of the surrounding string literal.

Field names must contain only letters, numbers, and underscores (`role_name` is valid, `role-name` is not). A field whose name contains an unsupported character might be accepted at catalog-definition save time but is not substituted at execution time, and the literal `{$form_field.*}` placeholder is emitted in the payload. If a placeholder references a field that was not provided on the access request, the placeholder is likewise left unchanged.

{% hint style="info" %}
Form field substitution and identity attribute substitution can be combined in the same payload. For example: `{"user": "{email}", "role": "{$form_field.role_name}"}` substitutes the identity's email from the source of identity and the role name from the access request form.
{% endhint %}

## Standard Active Directory attributes available for substitution

The following attributes are populated on the sync\_identities output entity for Active Directory integrations and can be used in variable substitutions:

| Attribute key         | Description                                                                                                                       |
| --------------------- | --------------------------------------------------------------------------------------------------------------------------------- |
| `email`               | Primary email address (`mail`)                                                                                                    |
| `given_name`          | Given name (`givenName`)                                                                                                          |
| `sur_name`            | Surname (`sn`)                                                                                                                    |
| `display_name`        | Display name (`displayName`)                                                                                                      |
| `department`          | Department                                                                                                                        |
| `title`               | Job title                                                                                                                         |
| `user_principal_name` | UPN (login name) (`userPrincipalName`)                                                                                            |
| `street_address`      | Street address (`streetAddress`)                                                                                                  |
| `password`            | Generated password (Early Access — requires password output; see [Password output (Early Access)](#password-output-early-access)) |

Custom properties defined in the integration configuration are also available, using the key `customprop_<property_name>` (where `<property_name>` is the property's format name as configured).

## Password output (Early Access)

When a [Sync Identities](/4yItIzMvkpAvMVFAamTf/features/lifecycle-management/policies-workflows/actions/sync-identities.md) or [Reset Password](/4yItIzMvkpAvMVFAamTf/features/lifecycle-management/policies-workflows/actions/reset-password.md) action precedes this action and password output is enabled, the password it generated is available to the webhook URL and JSON payload as `{EntityType.password}` — for example, `{ActiveDirectoryUser.password}`. This supports joiner workflows where Veza provisions an account and forwards the generated credentials to a downstream system such as an HR portal or ticketing API.

```
Payload: {"username": "{user_principal_name}", "password": "{ActiveDirectoryUser.password}"}
```

{% hint style="warning" %}
Passwords are passed as plain text to the target endpoint. Use this only when the workflow requires it, and ensure the endpoint uses HTTPS. Passwords are never written to the Veza database. They are available in memory during workflow execution only and are redacted from stored job payloads before persistence.
{% endhint %}

{% hint style="info" %}
**Early Access:** Veza Support enables password output for your tenant on request. The producing action ([Sync Identities](/4yItIzMvkpAvMVFAamTf/features/lifecycle-management/policies-workflows/actions/sync-identities.md) or [Reset Password](/4yItIzMvkpAvMVFAamTf/features/lifecycle-management/policies-workflows/actions/reset-password.md)) must also have password output enabled.
{% endhint %}

## Response Handling

When **Add response to output entities** is enabled, the action parses JSON responses and extracts specified entity data. This enables chaining actions where one API call creates a resource and returns an identifier that subsequent actions can reference.

For example, if a user creation API returns:

```json
{
  "result": {
    "user_id": "12345",
    "display_name": "John Doe"
  }
}
```

Configure the action with:

* Response Entity Attribute: `result`
* Response ID Attribute: `user_id`
* Response Name Attribute: `display_name`

The extracted entity becomes available to downstream workflow actions.

## HTTP Method Guidelines

* **GET**: Query operations, typically without payload; use for checking resource state or retrieving data. Does not set workflow change flags
* **POST**: Create new resources; requires JSON payload; sets both `AnyCreated` and `AnyChanges` flags that can trigger downstream actions with **Only send if prior actions resulted in a change** enabled
* **PUT**: Replace entire resources; requires JSON payload; sets `AnyChanges` flag
* **PATCH**: Partially update resources; requires JSON payload; sets `AnyChanges` flag
* **DELETE**: Remove resources; payload optional; sets `AnyChanges` flag
* **HEAD**: Metadata query without response body; payload optional; sets `AnyChanges` flag
* **OPTIONS**: Describes communication options for the target resource; payload optional; sets `AnyChanges` flag

> **Workflow Integration**: The `AnyCreated` and `AnyChanges` flags enable conditional workflow execution. Actions configured with **Only send if prior actions resulted in a change** will only execute when a previous action has set these flags, allowing you to build sophisticated conditional workflows (e.g., only send a notification webhook if a user was actually created, not just updated).

## Authentication Patterns

### Centrally-managed credentials

A stored REST credential supplies the authentication header for the request. Credentials live in the **REST/XML Credentials** table under **Administration** > **Credentials**, where one entry serves many actions. To add one, click **New REST/XML Credentials**. Sensitive fields are encrypted at rest, and an entry can carry a default URL and HTTP method for actions that set neither.

To use one, select it from the **Auth Credentials** dropdown in the action configuration. For endpoints that don't require authentication, such as internal services, pre-authenticated webhook URLs, or endpoints behind a VPN, select a credential of type **None**. See [REST Auth Credentials](/4yItIzMvkpAvMVFAamTf/features/lifecycle-management/policies-workflows/rest-auth-credentials.md) for the supported authentication types and their fields, including the OAuth2 grants Veza performs on your behalf. That page also covers the [token reuse window](/4yItIzMvkpAvMVFAamTf/features/lifecycle-management/policies-workflows/rest-auth-credentials.md#token-reuse-window), which governs how often Veza fetches a token.

A credential builds the authentication header and overrides the **Authorization Header (Legacy)** field. In the action editor, selecting any credential, including one of type **None**, clears the legacy header. For actions configured through the API, a **None** credential adds no header of its own and leaves an existing inline value in place.

### Inline authorization header

{% hint style="warning" %}
The inline **Authorization Header (Legacy)** field is deprecated. It appears only on actions that already have an inline header, under the **Legacy Authorization Header Detected** banner. You can't add one to a new action. Migrate existing configurations to a stored credential.
{% endhint %}

The field supports these authentication methods:

* **Bearer Token**: `Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...`
* **API Key**: `X-API-Key: secret-key-123` or `Authorization: ApiKey sk-prod-xyz`
* **Custom Headers**: Any header format your API requires

## Insight Point execution

Set **Data Source** to route the request through an Insight Point instead of the Veza control plane. Use this to reach endpoints that are not publicly accessible, such as internal APIs behind a firewall. Leave it empty to execute from the control plane.

| Setting     | Description                                                                                                                                                                                                                                                                                                                                                                           |
| ----------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Data Source | (Optional) Custom Provider data source to route the request through. The dropdown only shows Custom Providers configured with `external_lifecycle_management_type: SEND_REST_PAYLOAD`. If no data sources appear, see [Custom Application with Send REST Payload](/4yItIzMvkpAvMVFAamTf/features/lifecycle-management/policies-workflows/oaa-send-rest-payload.md) for configuration. |

{% hint style="warning" %}
**TLS certificates**: If the target API uses an internal or self-signed CA certificate, the Insight Point must trust that CA or the request will fail with `x509: certificate signed by unknown authority`. Configure the CA certificate in the Insight Point's truststore before enabling Insight Point routing. See [Custom Certificate Configuration](/4yItIzMvkpAvMVFAamTf/integrations/connectivity/insight-point/ova-v2.md#custom-certificate-configuration) (OVA) or [Using Custom Certificates](/4yItIzMvkpAvMVFAamTf/integrations/connectivity/insight-point/insight-point-install-script.md#using-custom-certificates) (install script).
{% endhint %}

## Test the connection

**Test Connection** checks whether Veza can reach the action's endpoint before the policy is saved. The button is the last item in the action's **Credentials** section, below **Auth Credentials**. It is enabled when the action has a **URL** or the selected credential has a default URL. Without a URL, the button is disabled.

When **Test Connection** is selected, Veza sends an HTTP `HEAD` request to the URL with a 10-second timeout:

* If **Data Source** is empty, Veza sends the request from the Veza control plane.
* If **Data Source** is set, Veza sends the request from that data source's Insight Point, as a job.

The test always uses `HEAD`, regardless of the action's **HTTP Method**. It does not send the action's request headers or payload, and it does not use the action's **Timeout in seconds** setting. Redirects are not followed, and `{attribute_name}` placeholders in the URL are not substituted during the test.

The result appears below the button.

{% hint style="warning" %}
Any HTTP response from the endpoint counts as reachable, including `401`, `403`, and `500`. A successful test confirms only that Veza can reach the endpoint from where the action runs. It does not confirm that the endpoint accepts the credentials, the HTTP method, the headers, or the payload.
{% endhint %}

How the test uses the selected credential:

* **Header**, **Basic**, and **Bearer** credentials are sent as-is and are not verified. For these types, the success message states that the credentials were not verified.
* If the credential has a URL, the tested URL must use the same host and port, and must not change the scheme from HTTPS to HTTP. Otherwise, Veza rejects the test and shows an error.
* If the credential has no URL, the test runs without the credential.

If the endpoint is reachable only from a private network and **Data Source** is empty, the test fails with a message that begins `Connection failed: unable to reach the endpoint from Veza's cloud`. Set **Data Source** to a data source whose Insight Point can reach the endpoint, then test again.

## Limitations

* Only JSON payloads are supported (no XML, form-data, or other formats)
* Authentication is header-based. Through a stored credential Veza can run the OAuth2 client credentials and password grants itself, but flows requiring interactive user consent are not supported
* Response parsing requires valid JSON if **Add response to output entities** is enabled
* Timeout applies to entire request; no automatic retry on failure
* POST, PUT, and PATCH methods require non-empty, valid JSON payloads

<details>

<summary>Example: Suspend Okta users via REST API</summary>

The Send REST Payload action can call Okta lifecycle APIs to suspend users, enabling workflows that handle leave of absence (LOA) scenarios before native Suspend action support is available.

**Configuration:**

| Setting              | Value                                                                                                                               |
| -------------------- | ----------------------------------------------------------------------------------------------------------------------------------- |
| **URL**              | `https://{your-okta-domain}/api/v1/users/{employee_id \| FROM_ENTITY_ATTRIBUTE,"OktaUser","employee_id","login"}/lifecycle/suspend` |
| **HTTP Method**      | `POST`                                                                                                                              |
| **Auth Credentials** | A **Header** credential with the value `SSWS {your-okta-api-token}`                                                                 |
| **JSON Payload**     | `{}`                                                                                                                                |

**Key notes:**

* **User identification**: Okta's suspend API requires the user's Okta ID or login. Use the `FROM_ENTITY_ATTRIBUTE` transformer to look up the Okta login from the Authorization Graph based on a source attribute like `employee_id`.
* **Authorization format**: Okta API tokens must be prefixed with `SSWS` (e.g., `SSWS 00abcd1234...`), not `Bearer`, so use a **Header** credential rather than a **Bearer** credential.
* **Empty payload**: The suspend endpoint requires a POST with an empty JSON object `{}` as the payload.

**Example workflow condition:**

To suspend users when their SOI lifecycle status changes to a leave state:

```scim
lifecycle_status eq "Leave" or lifecycle_status eq "Parental Leave" or lifecycle_status eq "Garden Leave"
```

**Unsuspending users**: To reactivate suspended users, create a separate workflow condition with the unsuspend endpoint:

```
https://{your-okta-domain}/api/v1/users/{employee_id | FROM_ENTITY_ATTRIBUTE,"OktaUser","employee_id","login"}/lifecycle/unsuspend
```

This approach is used when the SOI lifecycle status changes back to an active state (e.g., `lifecycle_status eq "Employed"`).

</details>


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://docs.veza.com/4yItIzMvkpAvMVFAamTf/features/lifecycle-management/policies-workflows/actions/send-rest-request.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
