Create Credential Group
curl --request POST \
--url https://api.thehyperstack.com/v1/groups/new \
--header 'Authorization: <authorization>' \
--header 'Content-Type: application/json' \
--data '
{
"title": "<string>",
"description": "<string>",
"tags": {},
"certificate_template": "<string>",
"badge_template": "<string>",
"url": "<string>",
"group_code": "<string>",
"does_expire": true,
"validity": 123,
"blockchain": true,
"do_notify": true
}
'import requests
url = "https://api.thehyperstack.com/v1/groups/new"
payload = {
"title": "<string>",
"description": "<string>",
"tags": {},
"certificate_template": "<string>",
"badge_template": "<string>",
"url": "<string>",
"group_code": "<string>",
"does_expire": True,
"validity": 123,
"blockchain": True,
"do_notify": True
}
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({
title: '<string>',
description: '<string>',
tags: {},
certificate_template: '<string>',
badge_template: '<string>',
url: '<string>',
group_code: '<string>',
does_expire: true,
validity: 123,
blockchain: true,
do_notify: true
})
};
fetch('https://api.thehyperstack.com/v1/groups/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/groups/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([
'title' => '<string>',
'description' => '<string>',
'tags' => [
],
'certificate_template' => '<string>',
'badge_template' => '<string>',
'url' => '<string>',
'group_code' => '<string>',
'does_expire' => true,
'validity' => 123,
'blockchain' => true,
'do_notify' => true
]),
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/groups/new"
payload := strings.NewReader("{\n \"title\": \"<string>\",\n \"description\": \"<string>\",\n \"tags\": {},\n \"certificate_template\": \"<string>\",\n \"badge_template\": \"<string>\",\n \"url\": \"<string>\",\n \"group_code\": \"<string>\",\n \"does_expire\": true,\n \"validity\": 123,\n \"blockchain\": true,\n \"do_notify\": true\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/groups/new")
.header("Authorization", "<authorization>")
.header("Content-Type", "application/json")
.body("{\n \"title\": \"<string>\",\n \"description\": \"<string>\",\n \"tags\": {},\n \"certificate_template\": \"<string>\",\n \"badge_template\": \"<string>\",\n \"url\": \"<string>\",\n \"group_code\": \"<string>\",\n \"does_expire\": true,\n \"validity\": 123,\n \"blockchain\": true,\n \"do_notify\": true\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.thehyperstack.com/v1/groups/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 \"title\": \"<string>\",\n \"description\": \"<string>\",\n \"tags\": {},\n \"certificate_template\": \"<string>\",\n \"badge_template\": \"<string>\",\n \"url\": \"<string>\",\n \"group_code\": \"<string>\",\n \"does_expire\": true,\n \"validity\": 123,\n \"blockchain\": true,\n \"do_notify\": true\n}"
response = http.request(request)
puts response.read_body{
"success": true,
"group_key": "Kq7Zp2LmX9aB"
}
{
"success": false,
"error": "Title and Description are required",
"error_code": "missing_title_description"
}
{
"success": false,
"error": "Either or both Badge and Certificate Template(s) required",
"error_code": "missing_templates"
}
{
"success": false,
"error": "Invalid Badge Template",
"error_code": "invalid_badge_template"
}
{
"success": false,
"error": "Invalid Certificate Template",
"error_code": "invalid_certificate_template"
}
{
"success": false,
"error": "tags must be a list of strings or a comma-separated string",
"error_code": "invalid_tags"
}
{
"success": false,
"error": "group_code must be text of at most 50 letters, digits, hyphens or spaces",
"error_code": "invalid_group_code"
}
{
"detail": "Invalid token or organization not found"
}
Credential Groups
Create Credential Group
POST
/
v1
/
groups
/
new
Create Credential Group
curl --request POST \
--url https://api.thehyperstack.com/v1/groups/new \
--header 'Authorization: <authorization>' \
--header 'Content-Type: application/json' \
--data '
{
"title": "<string>",
"description": "<string>",
"tags": {},
"certificate_template": "<string>",
"badge_template": "<string>",
"url": "<string>",
"group_code": "<string>",
"does_expire": true,
"validity": 123,
"blockchain": true,
"do_notify": true
}
'import requests
url = "https://api.thehyperstack.com/v1/groups/new"
payload = {
"title": "<string>",
"description": "<string>",
"tags": {},
"certificate_template": "<string>",
"badge_template": "<string>",
"url": "<string>",
"group_code": "<string>",
"does_expire": True,
"validity": 123,
"blockchain": True,
"do_notify": True
}
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({
title: '<string>',
description: '<string>',
tags: {},
certificate_template: '<string>',
badge_template: '<string>',
url: '<string>',
group_code: '<string>',
does_expire: true,
validity: 123,
blockchain: true,
do_notify: true
})
};
fetch('https://api.thehyperstack.com/v1/groups/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/groups/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([
'title' => '<string>',
'description' => '<string>',
'tags' => [
],
'certificate_template' => '<string>',
'badge_template' => '<string>',
'url' => '<string>',
'group_code' => '<string>',
'does_expire' => true,
'validity' => 123,
'blockchain' => true,
'do_notify' => true
]),
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/groups/new"
payload := strings.NewReader("{\n \"title\": \"<string>\",\n \"description\": \"<string>\",\n \"tags\": {},\n \"certificate_template\": \"<string>\",\n \"badge_template\": \"<string>\",\n \"url\": \"<string>\",\n \"group_code\": \"<string>\",\n \"does_expire\": true,\n \"validity\": 123,\n \"blockchain\": true,\n \"do_notify\": true\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/groups/new")
.header("Authorization", "<authorization>")
.header("Content-Type", "application/json")
.body("{\n \"title\": \"<string>\",\n \"description\": \"<string>\",\n \"tags\": {},\n \"certificate_template\": \"<string>\",\n \"badge_template\": \"<string>\",\n \"url\": \"<string>\",\n \"group_code\": \"<string>\",\n \"does_expire\": true,\n \"validity\": 123,\n \"blockchain\": true,\n \"do_notify\": true\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.thehyperstack.com/v1/groups/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 \"title\": \"<string>\",\n \"description\": \"<string>\",\n \"tags\": {},\n \"certificate_template\": \"<string>\",\n \"badge_template\": \"<string>\",\n \"url\": \"<string>\",\n \"group_code\": \"<string>\",\n \"does_expire\": true,\n \"validity\": 123,\n \"blockchain\": true,\n \"do_notify\": true\n}"
response = http.request(request)
puts response.read_body{
"success": true,
"group_key": "Kq7Zp2LmX9aB"
}
{
"success": false,
"error": "Title and Description are required",
"error_code": "missing_title_description"
}
{
"success": false,
"error": "Either or both Badge and Certificate Template(s) required",
"error_code": "missing_templates"
}
{
"success": false,
"error": "Invalid Badge Template",
"error_code": "invalid_badge_template"
}
{
"success": false,
"error": "Invalid Certificate Template",
"error_code": "invalid_certificate_template"
}
{
"success": false,
"error": "tags must be a list of strings or a comma-separated string",
"error_code": "invalid_tags"
}
{
"success": false,
"error": "group_code must be text of at most 50 letters, digits, hyphens or spaces",
"error_code": "invalid_group_code"
}
{
"detail": "Invalid token or organization not found"
}
Description
Creates a credential group. A group holds the credentials of one course, program or event, and sets their design and expiry. The legacy pathPOST /v1/group/new does the same.
New groups allow one credential per recipient email, and make credentials public. To change these settings, edit the group in the Studio.
Headers
string
required
Your API key:
Bearer YOUR_API_KEY. Create a key in the Studio under Settings → Developers.Body Parameters
string
required
Title of the group.
string
required
Description of the group.
array[string] | string
Tags for the group, as a list (
["security", "cloud"]) or a comma-separated string ("security, cloud"). Leave it out if you have none.string
Key of a certificate design in your organization. Send
certificate_template, badge_template or both. You find a design’s key at the end of the design editor’s URL in the Studio. An unknown key returns 400 with invalid_certificate_template.string
Key of a badge design in your organization. Send
certificate_template, badge_template or both. An unknown key returns 400 with invalid_badge_template.string
A web page for the group, such as the course page.
string
A short code for the group, such as
CSF-2026. Characters other than letters, numbers, hyphens and spaces are removed. What is left must be 50 characters or fewer, or the call returns 400 with invalid_group_code. If you leave it out, Hyperstack makes a random 8-character code.boolean
default:"false"
Set to
true to make credentials in this group expire.number
default:"0"
How many years a credential is valid after it is published. Used only when
does_expire is true.boolean
default:"false"
Set to
true to anchor credentials on the blockchain. It only takes effect if your plan includes blockchain.boolean
default:"true"
Set to
false to stop Hyperstack from emailing recipients when their credential is published.Success Response Fields
boolean
true when the group was created.string
The key of the new group. Use it to issue credentials in this group.
Responses
{
"success": true,
"group_key": "Kq7Zp2LmX9aB"
}
{
"success": false,
"error": "Title and Description are required",
"error_code": "missing_title_description"
}
{
"success": false,
"error": "Either or both Badge and Certificate Template(s) required",
"error_code": "missing_templates"
}
{
"success": false,
"error": "Invalid Badge Template",
"error_code": "invalid_badge_template"
}
{
"success": false,
"error": "Invalid Certificate Template",
"error_code": "invalid_certificate_template"
}
{
"success": false,
"error": "tags must be a list of strings or a comma-separated string",
"error_code": "invalid_tags"
}
{
"success": false,
"error": "group_code must be text of at most 50 letters, digits, hyphens or spaces",
"error_code": "invalid_group_code"
}
{
"detail": "Invalid token or organization not found"
}
curl -X POST "https://api.thehyperstack.com/v1/groups/new" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"title": "Cloud Security Fundamentals",
"description": "Awarded for completing the Cloud Security Fundamentals course.",
"tags": ["security", "cloud"],
"certificate_template": "cF7mN3pXs9Lh",
"badge_template": "bD4kR8tQw2Ze",
"url": "https://acme.example.com/courses/cloud-security",
"group_code": "CSF-2026",
"does_expire": true,
"validity": 2,
"do_notify": true
}'
Last modified on October 20, 2026
Was this page helpful?

