Create public client app (NONE auth)
POST {{apiPath}}/environments/{{envID}}/applications
This POST request creates a public client application with NONE authentication.
Public clients (SPAs, mobile apps, native apps) cannot securely store client secrets. Therefore, they use a tokenEndpointAuthMethod value of NONE and rely on PKCE (Proof Key for Code Exchange) for security.
The POST {{apiPath}}/environments/{{envID}}/applications endpoint creates the new native application. To configure this application to use PKCE to authenticate the token request, set the application’s pkceEnforcement property to S256_REQUIRED. With PKCE enforcement enabled, you must set the application’s tokenEndpointAuthMethod property to NONE.
The response returns information about the new application, including its id property, which identifies the ID for this application resource. The application’s ID is required to make the authorization request and to make the token request.
Body
raw ( application/json )
{
"enabled": true,
"name": "Shared-Native-App",
"description": "Public client application with NONE authentication - for SPAs and mobile apps that cannot securely store secrets. MUST use PKCE for security.",
"type": "NATIVE_APP",
"protocol": "OPENID_CONNECT",
"grantTypes": [
"AUTHORIZATION_CODE"
],
"redirectUris": [
"http://localhost:3000/callback"
],
"responseTypes": [
"CODE"
],
"tokenEndpointAuthMethod": "NONE",
"pkceEnforcement": "S256_REQUIRED"
}
Example Request
-
cURL
-
C#
-
Go
-
HTTP
-
Java
-
jQuery
-
NodeJS
-
Python
-
PHP
-
Ruby
-
Swift
curl --location --globoff '{{apiPath}}/environments/{{envID}}/applications' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer {{accessToken}}' \
--data '{
"enabled": true,
"name": "Shared-Native-App",
"description": "Public client application with NONE authentication - for SPAs and mobile apps that cannot securely store secrets. MUST use PKCE for security.",
"type": "NATIVE_APP",
"protocol": "OPENID_CONNECT",
"grantTypes": [
"AUTHORIZATION_CODE"
],
"redirectUris": [
"http://localhost:3000/callback"
],
"responseTypes": [
"CODE"
],
"tokenEndpointAuthMethod": "NONE",
"pkceEnforcement": "S256_REQUIRED"
}'
var options = new RestClientOptions("{{apiPath}}/environments/{{envID}}/applications")
{
MaxTimeout = -1,
};
var client = new RestClient(options);
var request = new RestRequest("", Method.Post);
request.AddHeader("Content-Type", "application/json");
request.AddHeader("Authorization", "Bearer {{accessToken}}");
var body = @"{" + "\n" +
@" ""enabled"": true," + "\n" +
@" ""name"": ""Shared-Native-App""," + "\n" +
@" ""description"": ""Public client application with NONE authentication - for SPAs and mobile apps that cannot securely store secrets. MUST use PKCE for security.""," + "\n" +
@" ""type"": ""NATIVE_APP""," + "\n" +
@" ""protocol"": ""OPENID_CONNECT""," + "\n" +
@" ""grantTypes"": [" + "\n" +
@" ""AUTHORIZATION_CODE""" + "\n" +
@" ]," + "\n" +
@" ""redirectUris"": [" + "\n" +
@" ""http://localhost:3000/callback""" + "\n" +
@" ]," + "\n" +
@" ""responseTypes"": [" + "\n" +
@" ""CODE""" + "\n" +
@" ]," + "\n" +
@" ""tokenEndpointAuthMethod"": ""NONE""," + "\n" +
@" ""pkceEnforcement"": ""S256_REQUIRED""" + "\n" +
@"}";
request.AddStringBody(body, DataFormat.Json);
RestResponse response = await client.ExecuteAsync(request);
Console.WriteLine(response.Content);
package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "{{apiPath}}/environments/{{envID}}/applications"
method := "POST"
payload := strings.NewReader(`{
"enabled": true,
"name": "Shared-Native-App",
"description": "Public client application with NONE authentication - for SPAs and mobile apps that cannot securely store secrets. MUST use PKCE for security.",
"type": "NATIVE_APP",
"protocol": "OPENID_CONNECT",
"grantTypes": [
"AUTHORIZATION_CODE"
],
"redirectUris": [
"http://localhost:3000/callback"
],
"responseTypes": [
"CODE"
],
"tokenEndpointAuthMethod": "NONE",
"pkceEnforcement": "S256_REQUIRED"
}`)
client := &http.Client {
}
req, err := http.NewRequest(method, url, payload)
if err != nil {
fmt.Println(err)
return
}
req.Header.Add("Content-Type", "application/json")
req.Header.Add("Authorization", "Bearer {{accessToken}}")
res, err := client.Do(req)
if err != nil {
fmt.Println(err)
return
}
defer res.Body.Close()
body, err := io.ReadAll(res.Body)
if err != nil {
fmt.Println(err)
return
}
fmt.Println(string(body))
}
POST /environments/{{envID}}/applications HTTP/1.1
Host: {{apiPath}}
Content-Type: application/json
Authorization: Bearer {{accessToken}}
{
"enabled": true,
"name": "Shared-Native-App",
"description": "Public client application with NONE authentication - for SPAs and mobile apps that cannot securely store secrets. MUST use PKCE for security.",
"type": "NATIVE_APP",
"protocol": "OPENID_CONNECT",
"grantTypes": [
"AUTHORIZATION_CODE"
],
"redirectUris": [
"http://localhost:3000/callback"
],
"responseTypes": [
"CODE"
],
"tokenEndpointAuthMethod": "NONE",
"pkceEnforcement": "S256_REQUIRED"
}
OkHttpClient client = new OkHttpClient().newBuilder()
.build();
MediaType mediaType = MediaType.parse("application/json");
RequestBody body = RequestBody.create(mediaType, "{\n \"enabled\": true,\n \"name\": \"Shared-Native-App\",\n \"description\": \"Public client application with NONE authentication - for SPAs and mobile apps that cannot securely store secrets. MUST use PKCE for security.\",\n \"type\": \"NATIVE_APP\",\n \"protocol\": \"OPENID_CONNECT\",\n \"grantTypes\": [\n \"AUTHORIZATION_CODE\"\n ],\n \"redirectUris\": [\n \"http://localhost:3000/callback\"\n ],\n \"responseTypes\": [\n \"CODE\"\n ],\n \"tokenEndpointAuthMethod\": \"NONE\",\n \"pkceEnforcement\": \"S256_REQUIRED\"\n}");
Request request = new Request.Builder()
.url("{{apiPath}}/environments/{{envID}}/applications")
.method("POST", body)
.addHeader("Content-Type", "application/json")
.addHeader("Authorization", "Bearer {{accessToken}}")
.build();
Response response = client.newCall(request).execute();
var settings = {
"url": "{{apiPath}}/environments/{{envID}}/applications",
"method": "POST",
"timeout": 0,
"headers": {
"Content-Type": "application/json",
"Authorization": "Bearer {{accessToken}}"
},
"data": JSON.stringify({
"enabled": true,
"name": "Shared-Native-App",
"description": "Public client application with NONE authentication - for SPAs and mobile apps that cannot securely store secrets. MUST use PKCE for security.",
"type": "NATIVE_APP",
"protocol": "OPENID_CONNECT",
"grantTypes": [
"AUTHORIZATION_CODE"
],
"redirectUris": [
"http://localhost:3000/callback"
],
"responseTypes": [
"CODE"
],
"tokenEndpointAuthMethod": "NONE",
"pkceEnforcement": "S256_REQUIRED"
}),
};
$.ajax(settings).done(function (response) {
console.log(response);
});
var request = require('request');
var options = {
'method': 'POST',
'url': '{{apiPath}}/environments/{{envID}}/applications',
'headers': {
'Content-Type': 'application/json',
'Authorization': 'Bearer {{accessToken}}'
},
body: JSON.stringify({
"enabled": true,
"name": "Shared-Native-App",
"description": "Public client application with NONE authentication - for SPAs and mobile apps that cannot securely store secrets. MUST use PKCE for security.",
"type": "NATIVE_APP",
"protocol": "OPENID_CONNECT",
"grantTypes": [
"AUTHORIZATION_CODE"
],
"redirectUris": [
"http://localhost:3000/callback"
],
"responseTypes": [
"CODE"
],
"tokenEndpointAuthMethod": "NONE",
"pkceEnforcement": "S256_REQUIRED"
})
};
request(options, function (error, response) {
if (error) throw new Error(error);
console.log(response.body);
});
import requests
import json
url = "{{apiPath}}/environments/{{envID}}/applications"
payload = json.dumps({
"enabled": True,
"name": "Shared-Native-App",
"description": "Public client application with NONE authentication - for SPAs and mobile apps that cannot securely store secrets. MUST use PKCE for security.",
"type": "NATIVE_APP",
"protocol": "OPENID_CONNECT",
"grantTypes": [
"AUTHORIZATION_CODE"
],
"redirectUris": [
"http://localhost:3000/callback"
],
"responseTypes": [
"CODE"
],
"tokenEndpointAuthMethod": "NONE",
"pkceEnforcement": "S256_REQUIRED"
})
headers = {
'Content-Type': 'application/json',
'Authorization': 'Bearer {{accessToken}}'
}
response = requests.request("POST", url, headers=headers, data=payload)
print(response.text)
<?php
require_once 'HTTP/Request2.php';
$request = new HTTP_Request2();
$request->setUrl('{{apiPath}}/environments/{{envID}}/applications');
$request->setMethod(HTTP_Request2::METHOD_POST);
$request->setConfig(array(
'follow_redirects' => TRUE
));
$request->setHeader(array(
'Content-Type' => 'application/json',
'Authorization' => 'Bearer {{accessToken}}'
));
$request->setBody('{\n "enabled": true,\n "name": "Shared-Native-App",\n "description": "Public client application with NONE authentication - for SPAs and mobile apps that cannot securely store secrets. MUST use PKCE for security.",\n "type": "NATIVE_APP",\n "protocol": "OPENID_CONNECT",\n "grantTypes": [\n "AUTHORIZATION_CODE"\n ],\n "redirectUris": [\n "http://localhost:3000/callback"\n ],\n "responseTypes": [\n "CODE"\n ],\n "tokenEndpointAuthMethod": "NONE",\n "pkceEnforcement": "S256_REQUIRED"\n}');
try {
$response = $request->send();
if ($response->getStatus() == 200) {
echo $response->getBody();
}
else {
echo 'Unexpected HTTP status: ' . $response->getStatus() . ' ' .
$response->getReasonPhrase();
}
}
catch(HTTP_Request2_Exception $e) {
echo 'Error: ' . $e->getMessage();
}
require "uri"
require "json"
require "net/http"
url = URI("{{apiPath}}/environments/{{envID}}/applications")
http = Net::HTTP.new(url.host, url.port);
request = Net::HTTP::Post.new(url)
request["Content-Type"] = "application/json"
request["Authorization"] = "Bearer {{accessToken}}"
request.body = JSON.dump({
"enabled": true,
"name": "Shared-Native-App",
"description": "Public client application with NONE authentication - for SPAs and mobile apps that cannot securely store secrets. MUST use PKCE for security.",
"type": "NATIVE_APP",
"protocol": "OPENID_CONNECT",
"grantTypes": [
"AUTHORIZATION_CODE"
],
"redirectUris": [
"http://localhost:3000/callback"
],
"responseTypes": [
"CODE"
],
"tokenEndpointAuthMethod": "NONE",
"pkceEnforcement": "S256_REQUIRED"
})
response = http.request(request)
puts response.read_body
let parameters = "{\n \"enabled\": true,\n \"name\": \"Shared-Native-App\",\n \"description\": \"Public client application with NONE authentication - for SPAs and mobile apps that cannot securely store secrets. MUST use PKCE for security.\",\n \"type\": \"NATIVE_APP\",\n \"protocol\": \"OPENID_CONNECT\",\n \"grantTypes\": [\n \"AUTHORIZATION_CODE\"\n ],\n \"redirectUris\": [\n \"http://localhost:3000/callback\"\n ],\n \"responseTypes\": [\n \"CODE\"\n ],\n \"tokenEndpointAuthMethod\": \"NONE\",\n \"pkceEnforcement\": \"S256_REQUIRED\"\n}"
let postData = parameters.data(using: .utf8)
var request = URLRequest(url: URL(string: "{{apiPath}}/environments/{{envID}}/applications")!,timeoutInterval: Double.infinity)
request.addValue("application/json", forHTTPHeaderField: "Content-Type")
request.addValue("Bearer {{accessToken}}", forHTTPHeaderField: "Authorization")
request.httpMethod = "POST"
request.httpBody = postData
let task = URLSession.shared.dataTask(with: request) { data, response, error in
guard let data = data else {
print(String(describing: error))
return
}
print(String(data: data, encoding: .utf8)!)
}
task.resume()
Example Response
201 Created
{
"_links": {
"self": {
"href": "https://api.pingone.com/v1/environments/abfba8f6-49eb-49f5-a5d9-80ad5c98f9f6/applications/7e94e040-aef8-402a-80fe-01a954a03465"
},
"environment": {
"href": "https://api.pingone.com/v1/environments/abfba8f6-49eb-49f5-a5d9-80ad5c98f9f6"
},
"metadata": {
"href": "https://api.pingone.com/v1/environments/abfba8f6-49eb-49f5-a5d9-80ad5c98f9f6/applications/7e94e040-aef8-402a-80fe-01a954a03465/metadata"
},
"attributes": {
"href": "https://api.pingone.com/v1/environments/abfba8f6-49eb-49f5-a5d9-80ad5c98f9f6/applications/7e94e040-aef8-402a-80fe-01a954a03465/attributes"
},
"pushCredentials": {
"href": "https://api.pingone.com/v1/environments/abfba8f6-49eb-49f5-a5d9-80ad5c98f9f6/applications/7e94e040-aef8-402a-80fe-01a954a03465/pushCredentials"
},
"secret": {
"href": "https://api.pingone.com/v1/environments/abfba8f6-49eb-49f5-a5d9-80ad5c98f9f6/applications/7e94e040-aef8-402a-80fe-01a954a03465/secret"
},
"grants": {
"href": "https://api.pingone.com/v1/environments/abfba8f6-49eb-49f5-a5d9-80ad5c98f9f6/applications/7e94e040-aef8-402a-80fe-01a954a03465/grants"
},
"keyRotationPolicy": {
"href": "https://api.pingone.com/v1/environments/abfba8f6-49eb-49f5-a5d9-80ad5c98f9f6/keyRotationPolicies/1cb8d0b5-c7ba-42e8-a556-240ea2410f1d"
}
},
"environment": {
"id": "abfba8f6-49eb-49f5-a5d9-80ad5c98f9f6"
},
"id": "7e94e040-aef8-402a-80fe-01a954a03465",
"name": "Shared-Native-App",
"description": "Public client application with NONE authentication - for SPAs and mobile apps that cannot securely store secrets. MUST use PKCE for security.",
"enabled": true,
"hiddenFromAppPortal": false,
"type": "NATIVE_APP",
"protocol": "OPENID_CONNECT",
"createdAt": "2026-04-20T16:33:44.010Z",
"updatedAt": "2026-04-20T16:33:44.010Z",
"clientId": "7e94e040-aef8-402a-80fe-01a954a03465",
"assignActorRoles": false,
"mobile": {
"integrityDetection": {
"mode": "DISABLED"
},
"passcodeRefreshDuration": {
"duration": 30,
"timeUnit": "SECONDS"
},
"passcodeGracePeriod": 5
},
"responseTypes": [
"CODE"
],
"pkceEnforcement": "S256_REQUIRED",
"requestScopesForMultipleResourcesEnabled": false,
"redirectUris": [
"http://localhost:3000/callback"
],
"deviceTimeout": 600,
"grantTypes": [
"AUTHORIZATION_CODE"
],
"idpSignoff": false,
"additionalRefreshTokenReplayProtectionEnabled": true,
"tokenEndpointAuthMethod": "NONE",
"parRequirement": "OPTIONAL",
"devicePollingInterval": 5,
"parTimeout": 60,
"signing": {
"keyRotationPolicy": {
"id": "1cb8d0b5-c7ba-42e8-a556-240ea2410f1d"
}
}
}