Issue Credential
curl --request POST \
--url https://api.thehyperstack.com/v1/credentials/new \
--header 'Authorization: <authorization>' \
--header 'Content-Type: application/json' \
--data '
{
"recipient": {
"name": "<string>",
"email": "<string>"
},
"group_key": "<string>",
"custom_attributes": {}
}
'import requests
url = "https://api.thehyperstack.com/v1/credentials/new"
payload = {
"recipient": {
"name": "<string>",
"email": "<string>"
},
"group_key": "<string>",
"custom_attributes": {}
}
headers = {
"Authorization": "<authorization>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: '<authorization>', 'Content-Type': 'application/json'},
body: JSON.stringify({
recipient: {name: '<string>', email: '<string>'},
group_key: '<string>',
custom_attributes: {}
})
};
fetch('https://api.thehyperstack.com/v1/credentials/new', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.thehyperstack.com/v1/credentials/new",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'recipient' => [
'name' => '<string>',
'email' => '<string>'
],
'group_key' => '<string>',
'custom_attributes' => [
]
]),
CURLOPT_HTTPHEADER => [
"Authorization: <authorization>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.thehyperstack.com/v1/credentials/new"
payload := strings.NewReader("{\n \"recipient\": {\n \"name\": \"<string>\",\n \"email\": \"<string>\"\n },\n \"group_key\": \"<string>\",\n \"custom_attributes\": {}\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "<authorization>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.thehyperstack.com/v1/credentials/new")
.header("Authorization", "<authorization>")
.header("Content-Type", "application/json")
.body("{\n \"recipient\": {\n \"name\": \"<string>\",\n \"email\": \"<string>\"\n },\n \"group_key\": \"<string>\",\n \"custom_attributes\": {}\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.thehyperstack.com/v1/credentials/new")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = '<authorization>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"recipient\": {\n \"name\": \"<string>\",\n \"email\": \"<string>\"\n },\n \"group_key\": \"<string>\",\n \"custom_attributes\": {}\n}"
response = http.request(request)
puts response.read_body{
"success": true,
"status": "published",
"document_id": "6f1c2a8e-3b4d-4e5f-9a7b-1c2d3e4f5a6b",
"document_url": "https://hyperstack.id/credential/6f1c2a8e-3b4d-4e5f-9a7b-1c2d3e4f5a6b",
"recipient": { "name": "Jane Doe", "email": "jane.doe@example.com" },
"group": { "title": "Cloud Security Fundamentals", "key": "Kq7Zp2LmX9aB", "code": "CSF-2026" },
"issued_on": "2026-03-15T10:30:00.412870Z",
"valid_until": null,
"metadata": { "custom_grade": "A" },
"privacy": "public"
}
{
"success": false,
"error": "Recipient Name and Email are required",
"error_code": "missing_recipient"
}
{
"success": false,
"error": "recipient must be an object with name and email",
"error_code": "invalid_recipient"
}
{
"success": false,
"error": "recipient email is not a valid email address",
"error_code": "invalid_email"
}
{
"success": false,
"error": "custom_attributes must be an object of attribute names and values",
"error_code": "invalid_custom_attributes"
}
{
"success": false,
"error": "Low balance",
"error_code": "low_balance"
}
{
"success": false,
"error": "Group Not Found",
"error_code": "group_not_found"
}
{
"success": false,
"error": "Credential already exists for this recipient, to overwrite, set duplication to true in group settings.",
"error_code": "credential_exists"
}
{
"detail": "Invalid token or organization not found"
}
Credentials
Issue Credential
POST
/
v1
/
credentials
/
new
Issue Credential
curl --request POST \
--url https://api.thehyperstack.com/v1/credentials/new \
--header 'Authorization: <authorization>' \
--header 'Content-Type: application/json' \
--data '
{
"recipient": {
"name": "<string>",
"email": "<string>"
},
"group_key": "<string>",
"custom_attributes": {}
}
'import requests
url = "https://api.thehyperstack.com/v1/credentials/new"
payload = {
"recipient": {
"name": "<string>",
"email": "<string>"
},
"group_key": "<string>",
"custom_attributes": {}
}
headers = {
"Authorization": "<authorization>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: '<authorization>', 'Content-Type': 'application/json'},
body: JSON.stringify({
recipient: {name: '<string>', email: '<string>'},
group_key: '<string>',
custom_attributes: {}
})
};
fetch('https://api.thehyperstack.com/v1/credentials/new', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.thehyperstack.com/v1/credentials/new",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'recipient' => [
'name' => '<string>',
'email' => '<string>'
],
'group_key' => '<string>',
'custom_attributes' => [
]
]),
CURLOPT_HTTPHEADER => [
"Authorization: <authorization>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.thehyperstack.com/v1/credentials/new"
payload := strings.NewReader("{\n \"recipient\": {\n \"name\": \"<string>\",\n \"email\": \"<string>\"\n },\n \"group_key\": \"<string>\",\n \"custom_attributes\": {}\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "<authorization>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.thehyperstack.com/v1/credentials/new")
.header("Authorization", "<authorization>")
.header("Content-Type", "application/json")
.body("{\n \"recipient\": {\n \"name\": \"<string>\",\n \"email\": \"<string>\"\n },\n \"group_key\": \"<string>\",\n \"custom_attributes\": {}\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.thehyperstack.com/v1/credentials/new")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = '<authorization>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"recipient\": {\n \"name\": \"<string>\",\n \"email\": \"<string>\"\n },\n \"group_key\": \"<string>\",\n \"custom_attributes\": {}\n}"
response = http.request(request)
puts response.read_body{
"success": true,
"status": "published",
"document_id": "6f1c2a8e-3b4d-4e5f-9a7b-1c2d3e4f5a6b",
"document_url": "https://hyperstack.id/credential/6f1c2a8e-3b4d-4e5f-9a7b-1c2d3e4f5a6b",
"recipient": { "name": "Jane Doe", "email": "jane.doe@example.com" },
"group": { "title": "Cloud Security Fundamentals", "key": "Kq7Zp2LmX9aB", "code": "CSF-2026" },
"issued_on": "2026-03-15T10:30:00.412870Z",
"valid_until": null,
"metadata": { "custom_grade": "A" },
"privacy": "public"
}
{
"success": false,
"error": "Recipient Name and Email are required",
"error_code": "missing_recipient"
}
{
"success": false,
"error": "recipient must be an object with name and email",
"error_code": "invalid_recipient"
}
{
"success": false,
"error": "recipient email is not a valid email address",
"error_code": "invalid_email"
}
{
"success": false,
"error": "custom_attributes must be an object of attribute names and values",
"error_code": "invalid_custom_attributes"
}
{
"success": false,
"error": "Low balance",
"error_code": "low_balance"
}
{
"success": false,
"error": "Group Not Found",
"error_code": "group_not_found"
}
{
"success": false,
"error": "Credential already exists for this recipient, to overwrite, set duplication to true in group settings.",
"error_code": "credential_exists"
}
{
"detail": "Invalid token or organization not found"
}
Description
Issues a credential to a recipient in a credential group, and publishes it at once. Publishing runs in the background and takes a few seconds. When it is done, the recipient gets an email (unless the group’s notifications are off), and Hyperstack sends acredential.issued webhook if you subscribed to one. Publishing may use a credit. A recipient already covered by a credit uses none.
The legacy path POST /v1/credential/issue does the same.
To create a credential without publishing it, use Generate Credential.
Headers
string
required
Your API key:
Bearer YOUR_API_KEY. Create a key in the Studio under Settings → Developers.Body Parameters
object
required
string
required
Key of the group to issue the credential in.
object
Values for your custom attributes, such as
{"custom_grade": "A"}. Each key is the merge tag of an attribute, without brackets. You find them in the Studio under Settings → Attributes.Only attributes whose value belongs to Each credential are saved. Other keys are ignored. Values are saved as text.Success Response Fields
boolean
true when the credential was created.string
"published": the credential is being published. To see when it is live, call View Credential and look for the status active.string
ID of the new credential. Use it in the other credential endpoints.
string
Public page of the credential.
object
The recipient’s
name and email, as saved.object
The group’s
title, key and code.string
When the credential was created (ISO 8601, UTC).
string | null
null in this response. If the group’s credentials expire, the expiry date is set when the credential is published.object
The custom attribute values that were saved.
string
"public" or "private", from the group’s settings.Responses
{
"success": true,
"status": "published",
"document_id": "6f1c2a8e-3b4d-4e5f-9a7b-1c2d3e4f5a6b",
"document_url": "https://hyperstack.id/credential/6f1c2a8e-3b4d-4e5f-9a7b-1c2d3e4f5a6b",
"recipient": { "name": "Jane Doe", "email": "jane.doe@example.com" },
"group": { "title": "Cloud Security Fundamentals", "key": "Kq7Zp2LmX9aB", "code": "CSF-2026" },
"issued_on": "2026-03-15T10:30:00.412870Z",
"valid_until": null,
"metadata": { "custom_grade": "A" },
"privacy": "public"
}
{
"success": false,
"error": "Recipient Name and Email are required",
"error_code": "missing_recipient"
}
{
"success": false,
"error": "recipient must be an object with name and email",
"error_code": "invalid_recipient"
}
{
"success": false,
"error": "recipient email is not a valid email address",
"error_code": "invalid_email"
}
{
"success": false,
"error": "custom_attributes must be an object of attribute names and values",
"error_code": "invalid_custom_attributes"
}
{
"success": false,
"error": "Low balance",
"error_code": "low_balance"
}
{
"success": false,
"error": "Group Not Found",
"error_code": "group_not_found"
}
{
"success": false,
"error": "Credential already exists for this recipient, to overwrite, set duplication to true in group settings.",
"error_code": "credential_exists"
}
{
"detail": "Invalid token or organization not found"
}
By default a group allows one credential per recipient email, and a second one returns
409. To allow more, change the group’s settings in the Studio.curl -X POST "https://api.thehyperstack.com/v1/credentials/new" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"recipient": {
"name": "Jane Doe",
"email": "jane.doe@example.com"
},
"group_key": "Kq7Zp2LmX9aB",
"custom_attributes": {
"custom_grade": "A"
}
}'
Last modified on October 20, 2026
Was this page helpful?

