PingOne Platform APIs

Customer Credential Signing Request

POST {{customerCredentialSigningApiUrl}}

The credential signing service uses the POST {{customerCredentialSigningApiUrl}} operation to send credentials for signing. You must define your credential signing API URL to the service in credentialSigning.url when you Update Credential Issuer Profile.

Ping Identity makes available linkcredentials:working-with-pingone-apis/postman-and-pingone/download-the-pingone-postman-collections.adoc#credentials-collection[The PingOne Credentials API collections] to download. In those Postman collections for this request, Auth Type on the Authorization tab is set to Noauth solely for testing.

In your implementation, select the authorization suitable to your requirements.

Request Model

Refer to Customer credential signing request data model for full property descriptions.

purpose String Optional

payloads

Object[]

Required

payloads.payload

String

Required

payloads.kid

String

Required

payloads.credentialSigningKeyId

String

Required

Headers

Content-Type      application/json

Body

raw ( application/json )

{
    "purpose": "Sign Credential payload",
    "payloads": [
        {
            "payload": "{{credentialSigningHeaderBase64}}.{{credentialSigningPayloadBase64}}",
            "kid": "{{credentialSigningKeyKid}}",
            "credentialSigningKeyId": "{{credentialSigningKeyId}}"
        }
    ]
}

Example Request

  • cURL

  • C#

  • Go

  • HTTP

  • Java

  • jQuery

  • NodeJS

  • Python

  • PHP

  • Ruby

  • Swift

curl --location --globoff '{{customerCredentialSigningApiUrl}}' \
--header 'Content-Type: application/json' \
--data '{
    "purpose": "Sign Credential payload",
    "payloads": [
        {
            "payload": "{{credentialSigningHeaderBase64}}.{{credentialSigningPayloadBase64}}",
            "kid": "{{credentialSigningKeyKid}}",
            "credentialSigningKeyId": "{{credentialSigningKeyId}}"
        }
    ]
}'
var options = new RestClientOptions("{{customerCredentialSigningApiUrl}}")
{
  MaxTimeout = -1,
};
var client = new RestClient(options);
var request = new RestRequest("", Method.Post);
request.AddHeader("Content-Type", "application/json");
var body = @"{" + "\n" +
@"    ""purpose"": ""Sign Credential payload""," + "\n" +
@"    ""payloads"": [" + "\n" +
@"        {" + "\n" +
@"            ""payload"": ""{{credentialSigningHeaderBase64}}.{{credentialSigningPayloadBase64}}""," + "\n" +
@"            ""kid"": ""{{credentialSigningKeyKid}}""," + "\n" +
@"            ""credentialSigningKeyId"": ""{{credentialSigningKeyId}}""" + "\n" +
@"        }" + "\n" +
@"    ]" + "\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 := "{{customerCredentialSigningApiUrl}}"
  method := "POST"

  payload := strings.NewReader(`{
    "purpose": "Sign Credential payload",
    "payloads": [
        {
            "payload": "{{credentialSigningHeaderBase64}}.{{credentialSigningPayloadBase64}}",
            "kid": "{{credentialSigningKeyKid}}",
            "credentialSigningKeyId": "{{credentialSigningKeyId}}"
        }
    ]
}`)

  client := &http.Client {
  }
  req, err := http.NewRequest(method, url, payload)

  if err != nil {
    fmt.Println(err)
    return
  }
  req.Header.Add("Content-Type", "application/json")

  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 / HTTP/1.1
Host: {{customerCredentialSigningApiUrl}}
Content-Type: application/json

{
    "purpose": "Sign Credential payload",
    "payloads": [
        {
            "payload": "{{credentialSigningHeaderBase64}}.{{credentialSigningPayloadBase64}}",
            "kid": "{{credentialSigningKeyKid}}",
            "credentialSigningKeyId": "{{credentialSigningKeyId}}"
        }
    ]
}
OkHttpClient client = new OkHttpClient().newBuilder()
  .build();
MediaType mediaType = MediaType.parse("application/json");
RequestBody body = RequestBody.create(mediaType, "{\n    \"purpose\": \"Sign Credential payload\",\n    \"payloads\": [\n        {\n            \"payload\": \"{{credentialSigningHeaderBase64}}.{{credentialSigningPayloadBase64}}\",\n            \"kid\": \"{{credentialSigningKeyKid}}\",\n            \"credentialSigningKeyId\": \"{{credentialSigningKeyId}}\"\n        }\n    ]\n}");
Request request = new Request.Builder()
  .url("{{customerCredentialSigningApiUrl}}")
  .method("POST", body)
  .addHeader("Content-Type", "application/json")
  .build();
Response response = client.newCall(request).execute();
var settings = {
  "url": "{{customerCredentialSigningApiUrl}}",
  "method": "POST",
  "timeout": 0,
  "headers": {
    "Content-Type": "application/json"
  },
  "data": JSON.stringify({
    "purpose": "Sign Credential payload",
    "payloads": [
      {
        "payload": "{{credentialSigningHeaderBase64}}.{{credentialSigningPayloadBase64}}",
        "kid": "{{credentialSigningKeyKid}}",
        "credentialSigningKeyId": "{{credentialSigningKeyId}}"
      }
    ]
  }),
};

$.ajax(settings).done(function (response) {
  console.log(response);
});
var request = require('request');
var options = {
  'method': 'POST',
  'url': '{{customerCredentialSigningApiUrl}}',
  'headers': {
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    "purpose": "Sign Credential payload",
    "payloads": [
      {
        "payload": "{{credentialSigningHeaderBase64}}.{{credentialSigningPayloadBase64}}",
        "kid": "{{credentialSigningKeyKid}}",
        "credentialSigningKeyId": "{{credentialSigningKeyId}}"
      }
    ]
  })

};
request(options, function (error, response) {
  if (error) throw new Error(error);
  console.log(response.body);
});
import requests
import json

url = "{{customerCredentialSigningApiUrl}}"

payload = json.dumps({
  "purpose": "Sign Credential payload",
  "payloads": [
    {
      "payload": "{{credentialSigningHeaderBase64}}.{{credentialSigningPayloadBase64}}",
      "kid": "{{credentialSigningKeyKid}}",
      "credentialSigningKeyId": "{{credentialSigningKeyId}}"
    }
  ]
})
headers = {
  'Content-Type': 'application/json'
}

response = requests.request("POST", url, headers=headers, data=payload)

print(response.text)
<?php
require_once 'HTTP/Request2.php';
$request = new HTTP_Request2();
$request->setUrl('{{customerCredentialSigningApiUrl}}');
$request->setMethod(HTTP_Request2::METHOD_POST);
$request->setConfig(array(
  'follow_redirects' => TRUE
));
$request->setHeader(array(
  'Content-Type' => 'application/json'
));
$request->setBody('{\n    "purpose": "Sign Credential payload",\n    "payloads": [\n        {\n            "payload": "{{credentialSigningHeaderBase64}}.{{credentialSigningPayloadBase64}}",\n            "kid": "{{credentialSigningKeyKid}}",\n            "credentialSigningKeyId": "{{credentialSigningKeyId}}"\n        }\n    ]\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("{{customerCredentialSigningApiUrl}}")

http = Net::HTTP.new(url.host, url.port);
request = Net::HTTP::Post.new(url)
request["Content-Type"] = "application/json"
request.body = JSON.dump({
  "purpose": "Sign Credential payload",
  "payloads": [
    {
      "payload": "{{credentialSigningHeaderBase64}}.{{credentialSigningPayloadBase64}}",
      "kid": "{{credentialSigningKeyKid}}",
      "credentialSigningKeyId": "{{credentialSigningKeyId}}"
    }
  ]
})

response = http.request(request)
puts response.read_body
let parameters = "{\n    \"purpose\": \"Sign Credential payload\",\n    \"payloads\": [\n        {\n            \"payload\": \"{{credentialSigningHeaderBase64}}.{{credentialSigningPayloadBase64}}\",\n            \"kid\": \"{{credentialSigningKeyKid}}\",\n            \"credentialSigningKeyId\": \"{{credentialSigningKeyId}}\"\n        }\n    ]\n}"
let postData = parameters.data(using: .utf8)

var request = URLRequest(url: URL(string: "{{customerCredentialSigningApiUrl}}")!,timeoutInterval: Double.infinity)
request.addValue("application/json", forHTTPHeaderField: "Content-Type")

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

200 OK

{
    "signedData": [
        {
            "payload": "ewogICAgImFsZyI6ICJSUzI1NiIsCiAgICAidHlwZSI6ICJKV1QiCn0=.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",
            "signature": "ERCkCxDvULSODX3UXC3qbpyu6WvGkp_HsDbMUP3Yt_cdagLMQNrRkBqrjDJRh4CWmFxTKtuHvsY2v4p_7b0JJCD_MkJ6_UctwEymDNcRa1ms95_xtvSz8-XQmwqJ8ES7mD-_8qfDlgDl7upyYkUul3HxzRb3WzgaeSU_CIFQoCRHhaknMscpIpTKbZI1GE8Ghxe6EDmOPN34FoMbnjJbrEkigpymnBdhCRev3LbDLhw-7f45D1WBmeJ5kzOCqKtK6bl7yYHk03XPzjov3xdtoMCOHT9DfhpuTwaqR4SL3sc-Uc2GumoQNM5cpYP_1l1IgyZ2Ud2kpUdvQ1CEDbOaqw"
        }
    ]
}