Access Codes API
The Access Codes API lets you integrate Afterglow access code management into your own backend systems. Use it to automatically create or generate access codes when users sign up through your website, CRM, or any other platform.
Authentication
Section titled “Authentication”All requests must include your API key in the X-Api-Key header.
X-Api-Key: your-api-key-hereRequests without a valid API key receive a 401 Unauthorized response.
Endpoints
Section titled “Endpoints”Add an access code
Section titled “Add an access code”Create an access code with a specific value you choose.
POST /tenant-codes/add
| Field | Type | Description |
|---|---|---|
code | string | The access code value (must be globally unique across all workspaces) |
type | string | Code type: "Normal", "Premium", or "Upgrade" |
Returns 200 OK on success or 400 Bad Request if the code is empty or already exists.
Generate an access code
Section titled “Generate an access code”Let Afterglow generate a unique, random access code for you.
POST /tenant-codes/generate
| Field | Type | Description |
|---|---|---|
type | string | Code type: "Normal", "Premium", or "Upgrade" |
studyGroupPublicId | string (optional) | The study group (research arm) to enroll the redeemer into. Copy this value from the Studies section in the Backoffice. |
studyPublicId | string (optional) | The study the group belongs to. Optional and normally omitted — the group already determines its study. |
Both studyGroupPublicId and studyPublicId are optional. If you leave them out, you get an ordinary code with no study link — the existing behaviour is unchanged.
When you include studyGroupPublicId, the code enrols whoever redeems it into that study group. The request returns 400 Bad Request if:
- the study group is not found,
- the study is inactive or not found,
- a
studyPublicIdis supplied that the group does not belong to, or - a study is specified without a group.
The study group ID is shown and copyable in the Studies section of the Backoffice — it is not an internal number.
A request that links a study group looks like this:
{ "type": "Normal", "studyGroupPublicId": "<group-id>"}Returns 200 OK with the generated code:
{ "code": "ABCD-EFGH-JKLM"}The generated code is made up of three groups of four characters separated by dashes, and contains only uppercase letters and digits (excluding characters that are easy to confuse like I, O, 0, and 1).
Code types
Section titled “Code types”| Value | Description |
|---|---|
"Normal" | Standard access code for regular users |
"Premium" | Grants premium user status upon registration |
"Upgrade" | Upgrades an existing user to premium status |
Code examples
Section titled “Code examples”Add a code:
curl -X POST https://api.afterglow.ag/tenant-codes/add \ -H "Content-Type: application/json" \ -H "X-Api-Key: your-api-key-here" \ -d '{"code": "YOURCOMPANY-WLCM-2025", "type": "Normal"}'Generate a code:
curl -X POST https://api.afterglow.ag/tenant-codes/generate \ -H "Content-Type: application/json" \ -H "X-Api-Key: your-api-key-here" \ -d '{"type": "Normal"}'Node.js
Section titled “Node.js”const API_URL = "https://api.afterglow.ag";const API_KEY = "your-api-key-here";
// Add a specific access codeasync function addAccessCode(code, type = "Normal") { const response = await fetch(`${API_URL}/tenant-codes/add`, { method: "POST", headers: { "Content-Type": "application/json", "X-Api-Key": API_KEY, }, body: JSON.stringify({ code, type }), });
if (!response.ok) { throw new Error(`Failed to add code: ${response.status}`); }}
// Generate a random access codeasync function generateAccessCode(type = "Normal") { const response = await fetch(`${API_URL}/tenant-codes/generate`, { method: "POST", headers: { "Content-Type": "application/json", "X-Api-Key": API_KEY, }, body: JSON.stringify({ type }), });
if (!response.ok) { throw new Error(`Failed to generate code: ${response.status}`); }
const data = await response.json(); return data.code;}Python
Section titled “Python”import requests
API_URL = "https://api.afterglow.ag"API_KEY = "your-api-key-here"
headers = { "Content-Type": "application/json", "X-Api-Key": API_KEY,}
# Add a specific access codedef add_access_code(code: str, code_type: str = "Normal"): response = requests.post( f"{API_URL}/tenant-codes/add", headers=headers, json={"code": code, "type": code_type}, ) response.raise_for_status()
# Generate a random access codedef generate_access_code(code_type: str = "Normal") -> str: response = requests.post( f"{API_URL}/tenant-codes/generate", headers=headers, json={"type": code_type}, ) response.raise_for_status() return response.json()["code"]C# / .NET
Section titled “C# / .NET”using System.Net.Http.Json;
var client = new HttpClient{ BaseAddress = new Uri("https://api.afterglow.ag")};client.DefaultRequestHeaders.Add("X-Api-Key", "your-api-key-here");
// Add a specific access codeasync Task AddAccessCode(string code, string type = "Normal"){ var response = await client.PostAsJsonAsync( "/tenant-codes/add", new { code, type } ); response.EnsureSuccessStatusCode();}
// Generate a random access codeasync Task<string> GenerateAccessCode(string type = "Normal"){ var response = await client.PostAsJsonAsync( "/tenant-codes/generate", new { type } ); response.EnsureSuccessStatusCode();
var result = await response.Content.ReadFromJsonAsync<GenerateCodeResponse>(); return result.Code;}
record GenerateCodeResponse(string Code);<?php
$apiUrl = "https://api.afterglow.ag";$apiKey = "your-api-key-here";
// Add a specific access codefunction addAccessCode(string $code, string $type = "Normal"): void{ global $apiUrl, $apiKey;
$ch = curl_init("$apiUrl/tenant-codes/add"); curl_setopt_array($ch, [ CURLOPT_POST => true, CURLOPT_HTTPHEADER => [ "Content-Type: application/json", "X-Api-Key: $apiKey", ], CURLOPT_POSTFIELDS => json_encode(["code" => $code, "type" => $type]), CURLOPT_RETURNTRANSFER => true, ]);
$response = curl_exec($ch); $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); curl_close($ch);
if ($httpCode !== 200) { throw new Exception("Failed to add code: HTTP $httpCode"); }}
// Generate a random access codefunction generateAccessCode(string $type = "Normal"): string{ global $apiUrl, $apiKey;
$ch = curl_init("$apiUrl/tenant-codes/generate"); curl_setopt_array($ch, [ CURLOPT_POST => true, CURLOPT_HTTPHEADER => [ "Content-Type: application/json", "X-Api-Key: $apiKey", ], CURLOPT_POSTFIELDS => json_encode(["type" => $type]), CURLOPT_RETURNTRANSFER => true, ]);
$response = curl_exec($ch); $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); curl_close($ch);
if ($httpCode !== 200) { throw new Exception("Failed to generate code: HTTP $httpCode"); }
return json_decode($response, true)["code"];}