curl --request POST \
--url https://api.zenamu.com/v1/clients/{clientId}/passes \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"customEntryCount": {
"count": 3,
"validityTimeValue": 1,
"validityTimeUnit": "month"
},
"currency": "CZK",
"price": 0,
"passGroupId": 42,
"sendEmail": false
}
'import requests
url = "https://api.zenamu.com/v1/clients/{clientId}/passes"
payload = {
"customEntryCount": {
"count": 3,
"validityTimeValue": 1,
"validityTimeUnit": "month"
},
"currency": "CZK",
"price": 0,
"passGroupId": 42,
"sendEmail": False
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
customEntryCount: {count: 3, validityTimeValue: 1, validityTimeUnit: 'month'},
currency: 'CZK',
price: 0,
passGroupId: 42,
sendEmail: false
})
};
fetch('https://api.zenamu.com/v1/clients/{clientId}/passes', 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.zenamu.com/v1/clients/{clientId}/passes",
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([
'customEntryCount' => [
'count' => 3,
'validityTimeValue' => 1,
'validityTimeUnit' => 'month'
],
'currency' => 'CZK',
'price' => 0,
'passGroupId' => 42,
'sendEmail' => false
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"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.zenamu.com/v1/clients/{clientId}/passes"
payload := strings.NewReader("{\n \"customEntryCount\": {\n \"count\": 3,\n \"validityTimeValue\": 1,\n \"validityTimeUnit\": \"month\"\n },\n \"currency\": \"CZK\",\n \"price\": 0,\n \"passGroupId\": 42,\n \"sendEmail\": false\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
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.zenamu.com/v1/clients/{clientId}/passes")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"customEntryCount\": {\n \"count\": 3,\n \"validityTimeValue\": 1,\n \"validityTimeUnit\": \"month\"\n },\n \"currency\": \"CZK\",\n \"price\": 0,\n \"passGroupId\": 42,\n \"sendEmail\": false\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.zenamu.com/v1/clients/{clientId}/passes")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"customEntryCount\": {\n \"count\": 3,\n \"validityTimeValue\": 1,\n \"validityTimeUnit\": \"month\"\n },\n \"currency\": \"CZK\",\n \"price\": 0,\n \"passGroupId\": 42,\n \"sendEmail\": false\n}"
response = http.request(request)
puts response.read_body{
"statusCode": 200,
"message": "Success",
"data": {
"clientId": 123,
"numberOfEntries": 11,
"validTo": "2026-10-01"
}
}Grant entry passes to a client
Adds entry passes to one client’s account and returns their new balance in the target group.
Send passGroupId to choose which pass group
the entries land in. Omit it, or send null, and the entries go to your
studio’s default group — the behavior existing integrations rely on.
Explicitly sending that default group’s ID behaves the same way.
See Granting credits and passes for the end-to-end flow.
curl --request POST \
--url https://api.zenamu.com/v1/clients/{clientId}/passes \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"customEntryCount": {
"count": 3,
"validityTimeValue": 1,
"validityTimeUnit": "month"
},
"currency": "CZK",
"price": 0,
"passGroupId": 42,
"sendEmail": false
}
'import requests
url = "https://api.zenamu.com/v1/clients/{clientId}/passes"
payload = {
"customEntryCount": {
"count": 3,
"validityTimeValue": 1,
"validityTimeUnit": "month"
},
"currency": "CZK",
"price": 0,
"passGroupId": 42,
"sendEmail": False
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
customEntryCount: {count: 3, validityTimeValue: 1, validityTimeUnit: 'month'},
currency: 'CZK',
price: 0,
passGroupId: 42,
sendEmail: false
})
};
fetch('https://api.zenamu.com/v1/clients/{clientId}/passes', 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.zenamu.com/v1/clients/{clientId}/passes",
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([
'customEntryCount' => [
'count' => 3,
'validityTimeValue' => 1,
'validityTimeUnit' => 'month'
],
'currency' => 'CZK',
'price' => 0,
'passGroupId' => 42,
'sendEmail' => false
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"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.zenamu.com/v1/clients/{clientId}/passes"
payload := strings.NewReader("{\n \"customEntryCount\": {\n \"count\": 3,\n \"validityTimeValue\": 1,\n \"validityTimeUnit\": \"month\"\n },\n \"currency\": \"CZK\",\n \"price\": 0,\n \"passGroupId\": 42,\n \"sendEmail\": false\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
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.zenamu.com/v1/clients/{clientId}/passes")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"customEntryCount\": {\n \"count\": 3,\n \"validityTimeValue\": 1,\n \"validityTimeUnit\": \"month\"\n },\n \"currency\": \"CZK\",\n \"price\": 0,\n \"passGroupId\": 42,\n \"sendEmail\": false\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.zenamu.com/v1/clients/{clientId}/passes")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"customEntryCount\": {\n \"count\": 3,\n \"validityTimeValue\": 1,\n \"validityTimeUnit\": \"month\"\n },\n \"currency\": \"CZK\",\n \"price\": 0,\n \"passGroupId\": 42,\n \"sendEmail\": false\n}"
response = http.request(request)
puts response.read_body{
"statusCode": 200,
"message": "Success",
"data": {
"clientId": 123,
"numberOfEntries": 11,
"validTo": "2026-10-01"
}
}Authorizations
Your secret API key (zen_live_…), sent as Authorization: Bearer <key>. Backend-to-backend only — never expose it in a browser. See Authentication.
Path Parameters
The client's numeric id, taken from the id field of GET /v1/clients. This is not the opaque _id. Malformed values and numeric prefixes return 400.
x >= 1123
Body
How many credits or entries to grant, and for how long.
Show child attributes
Show child attributes
"CZK"
x >= 0Target pass group. Omit it or send null for the studio default group. A group belonging to another studio, or an unknown ID, is rejected with 400.
x >= 1
