---
title: Custom API requests
description: Ping CLI can make API requests to supported Ping Identity products, similar to using curl, using the connector's api subcommand. For example, pingcli pingone api.
component: pingcli
version: 1.0
page_id: pingcli:using_pingcli:making-api-requests
canonical_url: https://developer.pingidentity.com/pingcli/1.0/using_pingcli/making-api-requests.html
revdate: June 8, 2026
section_ids:
  benefits-of-using-ping-cli-over-curl: Benefits of using Ping CLI over cURL
  ping-cli-manages-the-api-authentication: Ping CLI manages the API authentication
  ping-cli-manages-the-base-url: Ping CLI manages the base URL
  ping-cli-performs-automatic-retries-of-transient-errors: Ping CLI performs automatic retries of transient errors
  ping-cli-works-with-early-access-and-feature-flagged-apis: Ping CLI works with early access and feature-flagged APIs
  making-a-request: Making a request
  available-flags: Available flags
  example-get-request: Example GET request
  example-post-request-using-data-from-a-file: Example POST request (using data from a file)
  example-post-request-using-inline-data: Example POST request (using inline data)
  example-post-request-using-a-custom-header: Example POST request (using a custom header)
  example-put-request-using-data-from-a-file: Example PUT request (using data from a file)
  example-delete-request: Example DELETE request
  example-filtering-output-in-scripts: "Example: filtering output in scripts"
  more-information: More information
---

# Custom API requests

Ping CLI can make API requests to supported Ping Identity products, similar to using `curl`, using the connector's `api` subcommand. For example, `pingcli pingone api`.

|   |                                                                                                                                                                                                                                                                                                                                       |
| - | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|   | A configured and authenticated service connection is required before running this command. If you have not yet connected a service, refer to [Connect Ping Identity services](connecting-ping-services.html). To authenticate after connecting, use `pingcli auth login` or the per-product `pingcli <connector> auth login` command. |

## Benefits of using Ping CLI over cURL

Using Ping CLI to make direct API requests against a Ping Identity deployment offers a number of benefits over using a tool like `curl` directly.

### Ping CLI manages the API authentication

With commands similar to `curl`, it is typically up to the developer to provide credentials in the required format or a valid OAuth bearer token with the request. With Ping CLI, the API authentication is managed by the CLI tool and injected into the API request without the developer needing to add it manually. This capability allows the developer to focus on the structure and content of the request and ultimately focus on managing the Ping Identity deployment.

For example, the PingOne API requires a valid OAuth 2.0 bearer token that is typically short lived and can expire. When using Ping CLI, the developer needs to configure the PingOne connection details in the Ping CLI configuration and issue the API request without needing to add any authentication to the request syntax. The Ping CLI tool manages getting a valid access token and, if necessary, the refresh of an existing access token, and adds the token to the request on behalf of the developer.

### Ping CLI manages the base URL

With commands similar to `curl`, it's typically up to the developer to provide the full URL in the request. This requirement typically means the developer has to create variables for the host name or port to be able to use the same script for development, test, or production. Ping CLI injects the base URL value according to the developer's CLI configuration, meaning the same requests can be used between multiple environments without the need for custom variables.

### Ping CLI performs automatic retries of transient errors

APIs of any hosted or deployed service may respond with transient errors, for example rate limiting, server congestion, or network issues. There are cases when the developer needs to handle these errors and invoke custom logic. However, errors that are considered transient should be retried automatically.

Ping CLI automatically retries transient errors silently to the developer, so if they are encountered on the rare occasion, the developer doesn't need to retry an API request manually or, if embedded in a script, need to code specific retry logic.

For example, if PingOne returns a `429` HTTP response code as a result of rate limiting, Ping CLI handles the `Retry-After` header and, if needed, invokes an exponential backoff retry method according to documented best practice on the [PingOne API documentation](https://developer.pingidentity.com/pingone-api/before-you-begin/retry-best-practices.html). This repeated request process happens silently to the developer and allows for resilience in scripting environment management.

### Ping CLI works with early access and feature-flagged APIs

The `api` subcommand is not limited to APIs that Ping CLI supports natively. If a Ping Identity product exposes an early access or feature-flagged endpoint that the CLI doesn't yet have a dedicated command for, it can still be called using the `api` subcommand. Because authentication and base URL handling are still managed automatically, developers get the same ergonomics for bleeding-edge endpoints as they do for fully-supported ones, with no need to fall back to `curl`.

## Making a request

The format for making a request is `pingcli <connector> api [flags] API_URI`, where `<connector>` is the name of the connected product. For example:

* `pingcli pingone api <uri>`: requests against the PingOne management API

The **API\_URI** is required and must be the API URI path omitting the base API path of the service. For example, with PingOne, a full URL might be documented in the [API documentation](https://developer.pingidentity.com/pingone-api/platform/applications/applications-1/read-all-applications.html) as:

`{{apiPath}}/environments/{{envID}}/applications`

Since Ping CLI injects the `apiPath` value, the **API\_URI** value to provide is `environments/{{envID}}/applications`. For example:

`pingcli pingone api environments/$ENVIRONMENT_ID/applications`

### Available flags

| Flag              | Short form | Description                                                                                                                                                          |
| ----------------- | ---------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `--http-method`   | `-m`       | The HTTP method to use for the request. (default `GET`) Options are: `GET`, `POST`, `PUT`, `PATCH`, `DELETE`.                                                        |
| `--data`          | (none)     | Path to a JSON file containing the request body. Required for `POST`, `PUT`, and `PATCH` requests.                                                                   |
| `--data-raw`      | (none)     | Inline JSON string to send as the request body. An alternative to `--data` when you don't want to create a file. Example: `--data-raw '{"name": "My environment"}'`. |
| `--header`        | `-r`       | A custom header to add to the request. Repeatable for multiple headers. Example: `--header "Content-Type: application/vnd.pingidentity.user.import+json"`.           |
| `--output-format` | `-O`       | The console output format. Options are: `json`, `ndjson`, `text`. (default `text`)                                                                                   |
| `--fail`          | `-f`       | Return a non-zero exit code when the HTTP response indicates a failure status (4xx or 5xx).                                                                          |

### Example `GET` request

The following example reads all applications for a PingOne environment.

```console
pingcli pingone api \
  environments/$PINGONE_ENVIRONMENT_ID/applications
```

> **Collapse: Expand example response**
>
> ```json
> {
>   "schemaVersion": "1.0",
>   "status": "success",
>   "message": "Custom request successful",
>   "data": {
>     "_links": {
>       "self": {
>         "href": "https://api.pingone.com/v1/environments/abfba8f6-49eb-49f5-a5d9-80ad5c98f9f6/applications"
>       }
>     },
>     "_embedded": {
>       "applications": [
>         {
>           "_links": {
>             "environment": {
>               "href": "https://api.pingone.com/v1/environments/abfba8f6-49eb-49f5-a5d9-80ad5c98f9f6"
>             },
>             "self": {
>               "href": "https://api.pingone.com/v1/environments/abfba8f6-49eb-49f5-a5d9-80ad5c98f9f6/applications/fb955fe0-9b00-4bd3-a64e-6054dc95eae3"
>             }
>           },
>           "environment": {
>             "id": "abfba8f6-49eb-49f5-a5d9-80ad5c98f9f6"
>           },
>           "id": "fb955fe0-9b00-4bd3-a64e-6054dc95eae3",
>           "name": "PingOne Admin Console",
>           "enabled": true,
>           "type": "PING_ONE_ADMIN_CONSOLE",
>           "protocol": "OPENID_CONNECT"
>         }
>       ]
>     },
>     "size": 1
>   },
>   "errors": [],
>   "meta": {
>     "command": "pingcli pingone api",
>     "api": { "httpStatus": 200 }
>   }
> }
> ```

### Example `POST` request (using data from a file)

The following example creates a new application in a PingOne environment. The API request payload is supplied from a JSON file.

```console
pingcli pingone api \
  -m POST \
  --data ./my-application.json \
  environments/$PINGONE_ENVIRONMENT_ID/applications
```

> **Collapse: Expand  contents**
>
> ```
> {
>     "enabled": true,
>     "name": "OIDC-Web-App",
>     "description": "Test Description - OIDC App (Web)",
>     "type": "WEB_APP",
>     "protocol": "OPENID_CONNECT",
>     "homePageUrl": "https://example.com/homePage",
>     "loginPageUrl": "https://example.com/loginPage",
>     "grantTypes": [
>         "AUTHORIZATION_CODE"
>     ],
>     "redirectUris": [
>         "https://example.com"
>     ],
>     "responseTypes": [
>         "CODE"
>     ],
>     "tokenEndpointAuthMethod": "CLIENT_SECRET_BASIC",
>     "pkceEnforcement": "REQUIRED"
> }
> ```

> **Collapse: Expand example response**
>
> ```json
> {
>   "schemaVersion": "1.0",
>   "status": "success",
>   "message": "Custom request successful",
>   "data": {
>     "_links": {
>       "self": {
>         "href": "https://api.pingone.com/v1/environments/abfba8f6-49eb-49f5-a5d9-80ad5c98f9f6/applications/403b2bb3-a151-42b2-99d5-5eae2b151215"
>       }
>     },
>     "environment": {
>       "id": "abfba8f6-49eb-49f5-a5d9-80ad5c98f9f6"
>     },
>     "id": "403b2bb3-a151-42b2-99d5-5eae2b151215",
>     "name": "OIDC-Web-App",
>     "enabled": true,
>     "type": "WEB_APP",
>     "protocol": "OPENID_CONNECT"
>   },
>   "errors": [],
>   "meta": {
>     "command": "pingcli pingone api",
>     "api": { "httpStatus": 201 }
>   }
> }
> ```

### Example `POST` request (using inline data)

The following example creates a new PingOne environment using inline JSON data. The `--data-raw` flag is useful in scripts when creating a temporary file is not desirable.

```console
pingcli pingone api \
  -m POST \
  --data-raw '{"name": "My New Environment", "region": {"id": "NA"}, "type": "SANDBOX"}' \
  environments
```

> **Collapse: Expand example response**
>
> ```json
> {
>   "schemaVersion": "1.0",
>   "status": "success",
>   "message": "Custom request successful",
>   "data": {
>     "_links": {
>       "self": {
>         "href": "https://api.pingone.com/v1/environments/c1e92b4a-3d7e-4f1a-a2c5-9b8d0e6f3a21"
>       }
>     },
>     "id": "c1e92b4a-3d7e-4f1a-a2c5-9b8d0e6f3a21",
>     "name": "My New Environment",
>     "region": {
>       "id": "NA"
>     },
>     "type": "SANDBOX"
>   },
>   "errors": [],
>   "meta": {
>     "command": "pingcli pingone api",
>     "api": { "httpStatus": 201 }
>   }
> }
> ```

### Example `POST` request (using a custom header)

Some PingOne APIs require a specific `Content-Type` header. The following example imports users using the bulk user import API, which requires a custom content type header.

```console
pingcli pingone api \
  -m POST \
  --header "Content-Type: application/vnd.pingidentity.user.import+json" \
  --data ./users.json \
  environments/$PINGONE_ENVIRONMENT_ID/users
```

### Example `PUT` request (using data from a file)

The following example updates an existing application in a PingOne environment.

```console
pingcli pingone api \
  -m PUT \
  --data ./my-application.json \
  environments/$PINGONE_ENVIRONMENT_ID/applications/$PINGONE_MY_APPLICATION_ID
```

> **Collapse: Expand  contents**
>
> ```
> {
>     "name": "AppName",
>     "description": "This is my UPDATED app description",
>     "protocol": "OPENID_CONNECT",
>     "type": "WEB_APP"
> }
> ```

> **Collapse: Expand example response**
>
> ```json
> {
>   "schemaVersion": "1.0",
>   "status": "success",
>   "message": "Custom request successful",
>   "data": {
>     "_links": {
>       "self": {
>         "href": "https://api.pingone.com/v1/environments/abfba8f6-49eb-49f5-a5d9-80ad5c98f9f6/applications/d64c5a69-51ed-4c73-b8bc-8a3fafa6d0ea"
>       }
>     },
>     "environment": {
>       "id": "abfba8f6-49eb-49f5-a5d9-80ad5c98f9f6"
>     },
>     "id": "d64c5a69-51ed-4c73-b8bc-8a3fafa6d0ea",
>     "name": "AppName",
>     "description": "this is my UPDATED app description",
>     "enabled": false,
>     "type": "WEB_APP",
>     "protocol": "OPENID_CONNECT"
>   },
>   "errors": [],
>   "meta": {
>     "command": "pingcli pingone api",
>     "api": { "httpStatus": 200 }
>   }
> }
> ```

### Example `DELETE` request

The following example deletes an application from a PingOne environment.

```console
pingcli pingone api \
  -m DELETE \
  environments/$PINGONE_ENVIRONMENT_ID/applications/$PINGONE_APPLICATION_ID
```

> **Collapse: Expand example response**
>
> ```json
> {
>   "schemaVersion": "1.0",
>   "status": "success",
>   "message": "Custom request successful",
>   "data": null,
>   "errors": [],
>   "meta": {
>     "command": "pingcli pingone api",
>     "api": { "httpStatus": 204 }
>   }
> }
> ```

### Example: filtering output in scripts

Use `-O json` to get machine-readable JSON output and pipe it to [jq](https://jqlang.org/) to extract specific fields. With `-O json`, the API response body is in the `data` field of the output envelope. This is useful in automation scripts where you need to extract a specific field for use in a subsequent command.

The following example lists all applications and extracts just their IDs.

```bash
pingcli pingone api \
  -O json \
  environments/$PINGONE_ENVIRONMENT_ID/applications \
  | jq -r '.data._embedded.applications[].id'
```

Use `--fail` to cause the command to return a non-zero exit code on any 4xx or 5xx response, making it compatible with `set -e` in shell scripts. When a request fails, the envelope's `errors` array contains structured error details.

```bash
set -e

pingcli pingone api \
  -O json \
  --fail \
  environments/$PINGONE_ENVIRONMENT_ID/applications \
  | jq -r '.data._embedded.applications[].id'
```

## More information

* [pingcli pingone api](../command_reference/pingcli_pingone_api.html)

* [Product compatibility](../product-compatibility.html)

* [Authenticating to services](authenticating-to-services.html)

* [JSON output schema reference](../output_schema_reference/output-schema-reference.html)

* [PingOne platform API reference](https://developer.pingidentity.com/pingone-api/introduction.html)
