all=true, returns publicly discoverable projects.Authorization header for API access. Supports multiple authentication methods:
FormUser anonymous - for public operationsFormUser tkn-{token} - for authenticated operations with legacy tokensFormUser tkn-{token},email:{email} - creates/links virtual user by emailFormUser tkn-{token},discord_id:{discord_id} - creates/links virtual user by Discord IDFormUser tkn-{token},{jwt_token} - user identification with JWT token (legacy)Bearer YOUR_TOKEN_HERE - recommended for API integrationsWhen using email: or discord_id: formats with FormUser tokens, the system automatically creates or reuses virtual users. Virtual users are accounts created on-the-fly for form submissions without requiring full user registration. This is useful for:
Virtual users created this way are marked as virtual accounts and work across Issues, Feature Requests, and Support Tickets.
Validation Rules:
email: format must match RFC 5322 email format. Invalid emails will fall back to anonymous access.discord_id: format must be numeric (digits only). Invalid discord_ids will fall back to anonymous access.Personal Access Tokens provide enhanced security and can be created and managed in your account settings. They are ideal for API integrations, automated scripts, and CI/CD pipelines. Tokens can have different permissions, including:
| Name | Type | Description |
|---|---|---|
| page optional | integer | Page number for pagination (default: 1) |
| all optional | boolean | When true, returns public/discoverable projects instead of the user’s member projects |
curl \ -H "Authorization: Bearer YOUR_API_TOKEN" \ "https://app.betahub.io/projects.json?page=123&all=true"
require "net/http" uri = URI("https://app.betahub.io/projects.json?page=123&all=true") http = Net::HTTP.new(uri.host, uri.port) http.use_ssl = true request = Net::HTTP::Get.new(uri) request["Authorization"] = "Bearer YOUR_API_TOKEN" response = http.request(request) puts response.body
import requests response = requests.get( "https://app.betahub.io/projects.json?page=123&all=true", headers={"Authorization": "Bearer YOUR_API_TOKEN"} ) print(response.json())
const response = await fetch("https://app.betahub.io/projects.json?page=123&all=true", { headers: { "Authorization": "Bearer YOUR_API_TOKEN" } }); const data = await response.json();
HttpClient client = HttpClient.newHttpClient(); HttpRequest request = HttpRequest.newBuilder() .uri(URI.create("https://app.betahub.io/projects.json?page=123&all=true")) .header("Authorization", "Bearer YOUR_API_TOKEN") .GET() .build(); HttpResponse<String> response = client.send( request, HttpResponse.BodyHandlers.ofString()); System.out.println(response.body());
{
"projects": [
{
"id": "string",
"name": "string",
"description": "string",
"created_at": "2026-03-12T10:30:00Z",
"updated_at": "2026-03-12T10:30:00Z"
}
],
"pagination": {
"current_page": 0,
"total_pages": 0,
"total_count": 0
}
}
Authorization header for API access. Supports multiple authentication methods:
FormUser anonymous - for public operationsFormUser tkn-{token} - for authenticated operations with legacy tokensFormUser tkn-{token},email:{email} - creates/links virtual user by emailFormUser tkn-{token},discord_id:{discord_id} - creates/links virtual user by Discord IDFormUser tkn-{token},{jwt_token} - user identification with JWT token (legacy)Bearer YOUR_TOKEN_HERE - recommended for API integrationsWhen using email: or discord_id: formats with FormUser tokens, the system automatically creates or reuses virtual users. Virtual users are accounts created on-the-fly for form submissions without requiring full user registration. This is useful for:
Virtual users created this way are marked as virtual accounts and work across Issues, Feature Requests, and Support Tickets.
Validation Rules:
email: format must match RFC 5322 email format. Invalid emails will fall back to anonymous access.discord_id: format must be numeric (digits only). Invalid discord_ids will fall back to anonymous access.Personal Access Tokens provide enhanced security and can be created and managed in your account settings. They are ideal for API integrations, automated scripts, and CI/CD pipelines. Tokens can have different permissions, including:
| Name | Type | Description |
|---|---|---|
| id required | string | The project ID (obfuscated format, e.g. “pr-1234567”) |
curl \ -H "Authorization: Bearer YOUR_API_TOKEN" \ "https://app.betahub.io/projects/123.json"
require "net/http" uri = URI("https://app.betahub.io/projects/123.json") http = Net::HTTP.new(uri.host, uri.port) http.use_ssl = true request = Net::HTTP::Get.new(uri) request["Authorization"] = "Bearer YOUR_API_TOKEN" response = http.request(request) puts response.body
import requests response = requests.get( "https://app.betahub.io/projects/123.json", headers={"Authorization": "Bearer YOUR_API_TOKEN"} ) print(response.json())
const response = await fetch("https://app.betahub.io/projects/123.json", { headers: { "Authorization": "Bearer YOUR_API_TOKEN" } }); const data = await response.json();
HttpClient client = HttpClient.newHttpClient(); HttpRequest request = HttpRequest.newBuilder() .uri(URI.create("https://app.betahub.io/projects/123.json")) .header("Authorization", "Bearer YOUR_API_TOKEN") .GET() .build(); HttpResponse<String> response = client.send( request, HttpResponse.BodyHandlers.ofString()); System.out.println(response.body());
{
"id": "string",
"name": "string",
"description": "string",
"access": "string",
"created_at": "2026-03-12T10:30:00Z",
"updated_at": "2026-03-12T10:30:00Z",
"url": "https://example.com",
"sentiment_analysis": true,
"support_knowledge": true,
"support_knowledge_chunks_size": 0,
"has_discord_bot": true,
"modules": {},
"platforms": [
"string"
],
"min_description_length": 0,
"min_suggestion_length": 0,
"latest_release": {
"id": 0,
"label": "string",
"description": "string",
"created_at": "2026-03-12T10:30:00Z",
"updated_at": "2026-03-12T10:30:00Z",
"url": "https://example.com"
}
}
{
"error": "string",
"status": "string"
}
{
"error": "string",
"status": "string"
}
Authorization header for API access. Supports multiple authentication methods:
FormUser anonymous - for public operationsFormUser tkn-{token} - for authenticated operations with legacy tokensFormUser tkn-{token},email:{email} - creates/links virtual user by emailFormUser tkn-{token},discord_id:{discord_id} - creates/links virtual user by Discord IDFormUser tkn-{token},{jwt_token} - user identification with JWT token (legacy)Bearer YOUR_TOKEN_HERE - recommended for API integrationsWhen using email: or discord_id: formats with FormUser tokens, the system automatically creates or reuses virtual users. Virtual users are accounts created on-the-fly for form submissions without requiring full user registration. This is useful for:
Virtual users created this way are marked as virtual accounts and work across Issues, Feature Requests, and Support Tickets.
Validation Rules:
email: format must match RFC 5322 email format. Invalid emails will fall back to anonymous access.discord_id: format must be numeric (digits only). Invalid discord_ids will fall back to anonymous access.Personal Access Tokens provide enhanced security and can be created and managed in your account settings. They are ideal for API integrations, automated scripts, and CI/CD pipelines. Tokens can have different permissions, including:
| Name | Type | Description |
|---|---|---|
| project_id required | string |
| Name | Type | Description |
|---|---|---|
| page optional | integer | Page number for pagination (default: 1) |
| per_page optional | integer | Number of issues per page (default: 20, max: 100) |
| status optional | string |
Filter issues by status
open
in_progress
resolved
closed
|
| priority optional | string |
Filter issues by priority
low
medium
high
critical
|
| Name | Type | Description |
|---|---|---|
| BetaHub-Project-ID required | string | BetaHub project ID, the same as the project_id |
curl \ -H "Authorization: Bearer YOUR_API_TOKEN" \ -H "BetaHub-Project-ID: 123" \ "https://app.betahub.io/projects/123/issues.json?page=123&per_page=123&status=open&priority=low"
require "net/http" uri = URI("https://app.betahub.io/projects/123/issues.json?page=123&per_page=123&status=open&priority=low") http = Net::HTTP.new(uri.host, uri.port) http.use_ssl = true request = Net::HTTP::Get.new(uri) request["Authorization"] = "Bearer YOUR_API_TOKEN" request["BetaHub-Project-ID"] = "123" response = http.request(request) puts response.body
import requests response = requests.get( "https://app.betahub.io/projects/123/issues.json?page=123&per_page=123&status=open&priority=low", headers={"Authorization": "Bearer YOUR_API_TOKEN", "BetaHub-Project-ID": "123"} ) print(response.json())
const response = await fetch("https://app.betahub.io/projects/123/issues.json?page=123&per_page=123&status=open&priority=low", { headers: { "Authorization": "Bearer YOUR_API_TOKEN", "BetaHub-Project-ID": "123" } }); const data = await response.json();
HttpClient client = HttpClient.newHttpClient(); HttpRequest request = HttpRequest.newBuilder() .uri(URI.create("https://app.betahub.io/projects/123/issues.json?page=123&per_page=123&status=open&priority=low")) .header("Authorization", "Bearer YOUR_API_TOKEN") .header("BetaHub-Project-ID", "123") .GET() .build(); HttpResponse<String> response = client.send( request, HttpResponse.BodyHandlers.ofString()); System.out.println(response.body());
{
"issues": [
{
"id": "1234abc",
"title": "App crashes on login screen",
"description": "When attempting to login, the app crashes after entering credentials.",
"status": "open",
"priority": "high",
"created_at": "2024-10-03T12:34:56Z",
"updated_at": "2024-10-03T12:34:56Z",
"score": 95,
"steps_to_reproduce": [
{
"step": "1. Open the app"
},
{
"step": "2. Enter login credentials"
},
{
"step": "3. Press login"
}
],
"assigned_to": {
"id": "12",
"name": "John Doe"
},
"reported_by": {
"id": "34",
"name": "Jane Smith"
},
"potential_duplicate": null,
"url": "https://app.betahub.io/projects/1/issues/1234abc"
}
],
"pagination": {
"current_page": 1,
"per_page": 20,
"total_pages": 5,
"total_count": 95
}
}
Creates a new issue for a project. Issues can be created in a draft mode, which allows for a step-by-step creation process.
draft=true to keep it hidden (returns a JWT token in the ‘token’ field) 2. Optionally upload media files (screenshots, videos, log files) using the respective endpoints with the JWT token 3. Optionally set reporter email using the set_reporter_email endpoint 4. Publish the issue using the publish endpoint to make it visibleIMPORTANT NOTES:
Bearer {jwt_token} for subsequent API calls after issue creationAuthorization header for API access. Supports multiple authentication methods:
FormUser anonymous - for public operationsFormUser tkn-{token} - for authenticated operations with legacy tokensFormUser tkn-{token},email:{email} - creates/links virtual user by emailFormUser tkn-{token},discord_id:{discord_id} - creates/links virtual user by Discord IDFormUser tkn-{token},{jwt_token} - user identification with JWT token (legacy)Bearer YOUR_TOKEN_HERE - recommended for API integrationsWhen using email: or discord_id: formats with FormUser tokens, the system automatically creates or reuses virtual users. Virtual users are accounts created on-the-fly for form submissions without requiring full user registration. This is useful for:
Virtual users created this way are marked as virtual accounts and work across Issues, Feature Requests, and Support Tickets.
Validation Rules:
email: format must match RFC 5322 email format. Invalid emails will fall back to anonymous access.discord_id: format must be numeric (digits only). Invalid discord_ids will fall back to anonymous access.Personal Access Tokens provide enhanced security and can be created and managed in your account settings. They are ideal for API integrations, automated scripts, and CI/CD pipelines. Tokens can have different permissions, including:
| Name | Type | Description |
|---|---|---|
| project_id required | string |
| Name | Type | Description |
|---|---|---|
| BetaHub-Project-ID required | string | BetaHub project ID, the same as the project_id |
Custom field values for the issue. Replace FIELD_IDENT with the field’s identifier (e.g., issue[custom][severity], issue[custom][platform]). Each project can define its own custom fields via the project settings. Field identifiers are snake_case strings (e.g., actual_result, player_cloud_id). You can find the available fields and their identifiers in the project’s Custom Fields settings page.
Field types and expected values: - text: Any string value.
true, false, 1, or 0.
Validation: If a custom field is marked as required in the project settings and is not provided (or blank), the API returns a 422 error indicating which field is missing. For single_select fields, the value must match one of the configured options exactly.
JSON format: When using application/json, send custom fields as a nested object: {"issue": {"description": "...", "custom": {"severity": "Major", "platform": "Steam"}}}.curl \ -X POST \ -H "Authorization: Bearer YOUR_API_TOKEN" \ -H "BetaHub-Project-ID: 123" \ -d "issue[title]=Example title" \ -d "issue[description]=Example description" \ -d "issue[unformatted_steps_to_reproduce]=string" \ -d "issue[release_id]=string" \ -d "issue[release_label]=string" \ -d "issue[source]=string" \ "https://app.betahub.io/projects/123/issues.json"
require "net/http" require "json" uri = URI("https://app.betahub.io/projects/123/issues.json") http = Net::HTTP.new(uri.host, uri.port) http.use_ssl = true request = Net::HTTP::Post.new(uri) request["Authorization"] = "Bearer YOUR_API_TOKEN" request["BetaHub-Project-ID"] = "123" request.set_form_data({ "issue[title]" => "Example title", "issue[description]" => "Example description", "issue[unformatted_steps_to_reproduce]" => "string", "issue[release_id]" => "string", "issue[release_label]" => "string", "issue[source]" => "string" }) response = http.request(request) puts response.body
import requests response = requests.post( "https://app.betahub.io/projects/123/issues.json", headers={"Authorization": "Bearer YOUR_API_TOKEN", "BetaHub-Project-ID": "123"}, data={"issue[title]": "Example title", "issue[description]": "Example description", "issue[unformatted_steps_to_reproduce]": "string", "issue[release_id]": "string", "issue[release_label]": "string", "issue[source]": "string"} ) print(response.json())
const response = await fetch("https://app.betahub.io/projects/123/issues.json", { method: "POST", headers: { "Authorization": "Bearer YOUR_API_TOKEN", "BetaHub-Project-ID": "123" } }); const data = await response.json();
HttpClient client = HttpClient.newHttpClient(); HttpRequest request = HttpRequest.newBuilder() .uri(URI.create("https://app.betahub.io/projects/123/issues.json")) .header("Authorization", "Bearer YOUR_API_TOKEN") .header("BetaHub-Project-ID", "123") .header("Content-Type", "application/json") .POST(HttpRequest.BodyPublishers.ofString("{\"issue[title]\":\"string\",\"issue[description]\":\"string\",\"issue[unformatted_steps_to_reproduce]\":\"string\",\"issue[release_id]\":\"string\",\"issue[release_label]\":\"string\",\"issue[source]\":\"string\",\"issue[custom][FIELD_IDENT]\":\"string\",\"issue[debug_trace]\":{\"steps\":[{\"severity\":\"info\",\"description\":\"Process started successfully\"},{\"severity\":\"warning\",\"description\":\"Memory usage is high\"},{\"severity\":\"danger\",\"description\":\"Critical error occurred\"}]},\"draft\":true}")) .build(); HttpResponse<String> response = client.send( request, HttpResponse.BodyHandlers.ofString()); System.out.println(response.body());
{
"issue[title]": "string",
"issue[description]": "string",
"issue[unformatted_steps_to_reproduce]": "string",
"issue[release_id]": "string",
"issue[release_label]": "string",
"issue[source]": "string",
"issue[custom][FIELD_IDENT]": "string",
"issue[debug_trace]": {
"steps": [
{
"severity": "info",
"description": "Process started successfully"
},
{
"severity": "warning",
"description": "Memory usage is high"
},
{
"severity": "danger",
"description": "Critical error occurred"
}
]
},
"draft": true
}
{
"issue[title]": "App crashes on login screen",
"issue[description]": "When attempting to login, the app crashes after entering credentials.",
"issue[unformatted_steps_to_reproduce]": "1. Open the app
2. Enter login credentials
3. Press login",
"draft": true
}
{
"error": "Auth token does not have permission to create releases",
"status": "forbidden"
}
{
"error": "Custom fields Severity is required, Custom fields Platform is required",
"status": 422
}
Authorization header for API access. Supports multiple authentication methods:
FormUser anonymous - for public operationsFormUser tkn-{token} - for authenticated operations with legacy tokensFormUser tkn-{token},email:{email} - creates/links virtual user by emailFormUser tkn-{token},discord_id:{discord_id} - creates/links virtual user by Discord IDFormUser tkn-{token},{jwt_token} - user identification with JWT token (legacy)Bearer YOUR_TOKEN_HERE - recommended for API integrationsWhen using email: or discord_id: formats with FormUser tokens, the system automatically creates or reuses virtual users. Virtual users are accounts created on-the-fly for form submissions without requiring full user registration. This is useful for:
Virtual users created this way are marked as virtual accounts and work across Issues, Feature Requests, and Support Tickets.
Validation Rules:
email: format must match RFC 5322 email format. Invalid emails will fall back to anonymous access.discord_id: format must be numeric (digits only). Invalid discord_ids will fall back to anonymous access.Personal Access Tokens provide enhanced security and can be created and managed in your account settings. They are ideal for API integrations, automated scripts, and CI/CD pipelines. Tokens can have different permissions, including:
| Name | Type | Description |
|---|---|---|
| project_id required | string |
| Name | Type | Description |
|---|---|---|
| query required | string | The search query string to match against issue titles and descriptions |
| skip_ids optional | string | Comma-separated list of issue IDs to exclude from results |
| partial optional | string |
When set to ‘true’, returns limited results optimized for autocomplete (max 4 results)
true
false
|
| scoped_id optional | string | Instead of searching, find a specific issue by its scoped ID (e.g., “123” or “g-456”) |
| Name | Type | Description |
|---|---|---|
| BetaHub-Project-ID required | string | BetaHub project ID, the same as the project_id |
curl \ -H "Authorization: Bearer YOUR_API_TOKEN" \ -H "BetaHub-Project-ID: 123" \ "https://app.betahub.io/projects/123/issues/search.json?query=example&skip_ids=123&partial=true&scoped_id=123"
require "net/http" uri = URI("https://app.betahub.io/projects/123/issues/search.json?query=example&skip_ids=123&partial=true&scoped_id=123") http = Net::HTTP.new(uri.host, uri.port) http.use_ssl = true request = Net::HTTP::Get.new(uri) request["Authorization"] = "Bearer YOUR_API_TOKEN" request["BetaHub-Project-ID"] = "123" response = http.request(request) puts response.body
import requests response = requests.get( "https://app.betahub.io/projects/123/issues/search.json?query=example&skip_ids=123&partial=true&scoped_id=123", headers={"Authorization": "Bearer YOUR_API_TOKEN", "BetaHub-Project-ID": "123"} ) print(response.json())
const response = await fetch("https://app.betahub.io/projects/123/issues/search.json?query=example&skip_ids=123&partial=true&scoped_id=123", { headers: { "Authorization": "Bearer YOUR_API_TOKEN", "BetaHub-Project-ID": "123" } }); const data = await response.json();
HttpClient client = HttpClient.newHttpClient(); HttpRequest request = HttpRequest.newBuilder() .uri(URI.create("https://app.betahub.io/projects/123/issues/search.json?query=example&skip_ids=123&partial=true&scoped_id=123")) .header("Authorization", "Bearer YOUR_API_TOKEN") .header("BetaHub-Project-ID", "123") .GET() .build(); HttpResponse<String> response = client.send( request, HttpResponse.BodyHandlers.ofString()); System.out.println(response.body());
{
"issues": [
{
"id": "1234abc",
"title": "App crashes on login screen",
"status": "open",
"priority": "high",
"created_at": "2024-10-03T12:34:56Z"
}
],
"pagination": {
"current_page": 1,
"per_page": 25,
"total_pages": 3,
"total_count": 68
},
"project_id": 123
}
{
"error": "string",
"status": "string"
}
{
"error": "string",
"status": "string"
}
Authorization header for API access. Supports multiple authentication methods:
FormUser anonymous - for public operationsFormUser tkn-{token} - for authenticated operations with legacy tokensFormUser tkn-{token},email:{email} - creates/links virtual user by emailFormUser tkn-{token},discord_id:{discord_id} - creates/links virtual user by Discord IDFormUser tkn-{token},{jwt_token} - user identification with JWT token (legacy)Bearer YOUR_TOKEN_HERE - recommended for API integrationsWhen using email: or discord_id: formats with FormUser tokens, the system automatically creates or reuses virtual users. Virtual users are accounts created on-the-fly for form submissions without requiring full user registration. This is useful for:
Virtual users created this way are marked as virtual accounts and work across Issues, Feature Requests, and Support Tickets.
Validation Rules:
email: format must match RFC 5322 email format. Invalid emails will fall back to anonymous access.discord_id: format must be numeric (digits only). Invalid discord_ids will fall back to anonymous access.Personal Access Tokens provide enhanced security and can be created and managed in your account settings. They are ideal for API integrations, automated scripts, and CI/CD pipelines. Tokens can have different permissions, including:
| Name | Type | Description |
|---|---|---|
| project_id required | string |
| Name | Type | Description |
|---|---|---|
| BetaHub-Project-ID required | string | BetaHub project ID, the same as the project_id |
curl \ -X POST \ -H "Authorization: Bearer YOUR_API_TOKEN" \ -H "BetaHub-Project-ID: 123" \ -d "query=string" \ -d "skip_ids=string" \ -d "partial=true" \ -d "scoped_id=string" \ "https://app.betahub.io/projects/123/issues/search.json"
require "net/http" require "json" uri = URI("https://app.betahub.io/projects/123/issues/search.json") http = Net::HTTP.new(uri.host, uri.port) http.use_ssl = true request = Net::HTTP::Post.new(uri) request["Authorization"] = "Bearer YOUR_API_TOKEN" request["BetaHub-Project-ID"] = "123" request.set_form_data({ "query" => "string", "skip_ids" => "string", "partial" => "true", "scoped_id" => "string" }) response = http.request(request) puts response.body
import requests response = requests.post( "https://app.betahub.io/projects/123/issues/search.json", headers={"Authorization": "Bearer YOUR_API_TOKEN", "BetaHub-Project-ID": "123"}, data={"query": "string", "skip_ids": "string", "partial": "true", "scoped_id": "string"} ) print(response.json())
const response = await fetch("https://app.betahub.io/projects/123/issues/search.json", { method: "POST", headers: { "Authorization": "Bearer YOUR_API_TOKEN", "BetaHub-Project-ID": "123" } }); const data = await response.json();
HttpClient client = HttpClient.newHttpClient(); HttpRequest request = HttpRequest.newBuilder() .uri(URI.create("https://app.betahub.io/projects/123/issues/search.json")) .header("Authorization", "Bearer YOUR_API_TOKEN") .header("BetaHub-Project-ID", "123") .header("Content-Type", "application/json") .POST(HttpRequest.BodyPublishers.ofString("{\"query\":\"string\",\"skip_ids\":\"string\",\"partial\":\"true\",\"scoped_id\":\"string\"}")) .build(); HttpResponse<String> response = client.send( request, HttpResponse.BodyHandlers.ofString()); System.out.println(response.body());
{
"query": "string",
"skip_ids": "string",
"partial": "true",
"scoped_id": "string"
}
{}
{
"error": "string",
"status": "string"
}
{
"error": "string",
"status": "string"
}
Authorization header for API access. Supports multiple authentication methods:
FormUser anonymous - for public operationsFormUser tkn-{token} - for authenticated operations with legacy tokensFormUser tkn-{token},email:{email} - creates/links virtual user by emailFormUser tkn-{token},discord_id:{discord_id} - creates/links virtual user by Discord IDFormUser tkn-{token},{jwt_token} - user identification with JWT token (legacy)Bearer YOUR_TOKEN_HERE - recommended for API integrationsWhen using email: or discord_id: formats with FormUser tokens, the system automatically creates or reuses virtual users. Virtual users are accounts created on-the-fly for form submissions without requiring full user registration. This is useful for:
Virtual users created this way are marked as virtual accounts and work across Issues, Feature Requests, and Support Tickets.
Validation Rules:
email: format must match RFC 5322 email format. Invalid emails will fall back to anonymous access.discord_id: format must be numeric (digits only). Invalid discord_ids will fall back to anonymous access.Personal Access Tokens provide enhanced security and can be created and managed in your account settings. They are ideal for API integrations, automated scripts, and CI/CD pipelines. Tokens can have different permissions, including:
| Name | Type | Description |
|---|---|---|
| project_id required | string | |
| issue_id required | string |
| Name | Type | Description |
|---|---|---|
| BetaHub-Project-ID required | string | BetaHub project ID, the same as the project_id |
curl \ -X PUT \ -H "Authorization: Bearer YOUR_API_TOKEN" \ -H "BetaHub-Project-ID: 123" \ -H "Content-Type: application/json" \ -d '{ "issue[title]": "string", "issue[description]": "string", "issue[status]": "open", "issue[priority]": "low", "issue[assigned_to_id]": "string", "issue[unformatted_steps_to_reproduce]": "string", "issue[release_id]": "string" }' \ "https://app.betahub.io/projects/123/issues/g-123.json"
require "net/http" require "json" uri = URI("https://app.betahub.io/projects/123/issues/g-123.json") http = Net::HTTP.new(uri.host, uri.port) http.use_ssl = true request = Net::HTTP::Put.new(uri) request["Authorization"] = "Bearer YOUR_API_TOKEN" request["BetaHub-Project-ID"] = "123" request["Content-Type"] = "application/json" request.body = { "issue[title]": "string", "issue[description]": "string", "issue[status]": "open", "issue[priority]": "low", "issue[assigned_to_id]": "string", "issue[unformatted_steps_to_reproduce]": "string", "issue[release_id]": "string" } response = http.request(request) puts response.body
import requests response = requests.put( "https://app.betahub.io/projects/123/issues/g-123.json", headers={"Authorization": "Bearer YOUR_API_TOKEN", "BetaHub-Project-ID": "123"}, json={ "issue[title]": "string", "issue[description]": "string", "issue[status]": "open", "issue[priority]": "low", "issue[assigned_to_id]": "string", "issue[unformatted_steps_to_reproduce]": "string", "issue[release_id]": "string" } ) print(response.json())
const response = await fetch("https://app.betahub.io/projects/123/issues/g-123.json", { method: "PUT", headers: { "Authorization": "Bearer YOUR_API_TOKEN", "BetaHub-Project-ID": "123", "Content-Type": "application/json" }, body: JSON.stringify({ "issue[title]": "string", "issue[description]": "string", "issue[status]": "open", "issue[priority]": "low", "issue[assigned_to_id]": "string", "issue[unformatted_steps_to_reproduce]": "string", "issue[release_id]": "string" }) }); const data = await response.json();
HttpClient client = HttpClient.newHttpClient(); HttpRequest request = HttpRequest.newBuilder() .uri(URI.create("https://app.betahub.io/projects/123/issues/g-123.json")) .header("Authorization", "Bearer YOUR_API_TOKEN") .header("BetaHub-Project-ID", "123") .header("Content-Type", "application/json") .PUT(HttpRequest.BodyPublishers.ofString("{\"issue[title]\":\"string\",\"issue[description]\":\"string\",\"issue[status]\":\"open\",\"issue[priority]\":\"low\",\"issue[assigned_to_id]\":\"string\",\"issue[unformatted_steps_to_reproduce]\":\"string\",\"issue[release_id]\":\"string\"}")) .build(); HttpResponse<String> response = client.send( request, HttpResponse.BodyHandlers.ofString()); System.out.println(response.body());
{
"issue[title]": "string",
"issue[description]": "string",
"issue[status]": "open",
"issue[priority]": "low",
"issue[assigned_to_id]": "string",
"issue[unformatted_steps_to_reproduce]": "string",
"issue[release_id]": "string"
}
{
"issue[title]": "Updated: App crashes on login screen",
"issue[description]": "Updated description with more details about the crash.",
"issue[status]": "in_progress",
"issue[priority]": "critical"
}
{
"error": "string",
"status": "string"
}
{
"error": "string",
"status": "string"
}
{
"error": "string",
"status": "string"
}
Authorization header for API access. Supports multiple authentication methods:
FormUser anonymous - for public operationsFormUser tkn-{token} - for authenticated operations with legacy tokensFormUser tkn-{token},email:{email} - creates/links virtual user by emailFormUser tkn-{token},discord_id:{discord_id} - creates/links virtual user by Discord IDFormUser tkn-{token},{jwt_token} - user identification with JWT token (legacy)Bearer YOUR_TOKEN_HERE - recommended for API integrationsWhen using email: or discord_id: formats with FormUser tokens, the system automatically creates or reuses virtual users. Virtual users are accounts created on-the-fly for form submissions without requiring full user registration. This is useful for:
Virtual users created this way are marked as virtual accounts and work across Issues, Feature Requests, and Support Tickets.
Validation Rules:
email: format must match RFC 5322 email format. Invalid emails will fall back to anonymous access.discord_id: format must be numeric (digits only). Invalid discord_ids will fall back to anonymous access.Personal Access Tokens provide enhanced security and can be created and managed in your account settings. They are ideal for API integrations, automated scripts, and CI/CD pipelines. Tokens can have different permissions, including:
| Name | Type | Description |
|---|---|---|
| project_id required | string | |
| issue_id required | string |
| Name | Type | Description |
|---|---|---|
| BetaHub-Project-ID required | string | BetaHub project ID, the same as the project_id |
curl \ -X POST \ -H "Authorization: Bearer YOUR_API_TOKEN" \ -H "BetaHub-Project-ID: 123" \ -H "Content-Type: application/json" \ -d '{ "email": "user@example.com", "discord_id": "string" }' \ "https://app.betahub.io/projects/123/issues/g-123/set_reporter_email"
require "net/http" require "json" uri = URI("https://app.betahub.io/projects/123/issues/g-123/set_reporter_email") http = Net::HTTP.new(uri.host, uri.port) http.use_ssl = true request = Net::HTTP::Post.new(uri) request["Authorization"] = "Bearer YOUR_API_TOKEN" request["BetaHub-Project-ID"] = "123" request["Content-Type"] = "application/json" request.body = { "email": "user@example.com", "discord_id": "string" } response = http.request(request) puts response.body
import requests response = requests.post( "https://app.betahub.io/projects/123/issues/g-123/set_reporter_email", headers={"Authorization": "Bearer YOUR_API_TOKEN", "BetaHub-Project-ID": "123"}, json={ "email": "user@example.com", "discord_id": "string" } ) print(response.json())
const response = await fetch("https://app.betahub.io/projects/123/issues/g-123/set_reporter_email", { method: "POST", headers: { "Authorization": "Bearer YOUR_API_TOKEN", "BetaHub-Project-ID": "123", "Content-Type": "application/json" }, body: JSON.stringify({ "email": "user@example.com", "discord_id": "string" }) }); const data = await response.json();
HttpClient client = HttpClient.newHttpClient(); HttpRequest request = HttpRequest.newBuilder() .uri(URI.create("https://app.betahub.io/projects/123/issues/g-123/set_reporter_email")) .header("Authorization", "Bearer YOUR_API_TOKEN") .header("BetaHub-Project-ID", "123") .header("Content-Type", "application/json") .POST(HttpRequest.BodyPublishers.ofString("{\"email\":\"user@example.com\",\"discord_id\":\"string\"}")) .build(); HttpResponse<String> response = client.send( request, HttpResponse.BodyHandlers.ofString()); System.out.println(response.body());
{
"email": "user@example.com",
"discord_id": "string"
}
{
"success": true,
"message": "string",
"issue_id": "string",
"reporter": {
"id": 0,
"email": "string",
"discord_id": "string",
"virtual": true
}
}
{
"error": "string",
"status": "string"
}
{
"error": "string",
"status": "string"
}
{
"error": "string",
"status": "string"
}
Authorization header for API access. Supports multiple authentication methods:
FormUser anonymous - for public operationsFormUser tkn-{token} - for authenticated operations with legacy tokensFormUser tkn-{token},email:{email} - creates/links virtual user by emailFormUser tkn-{token},discord_id:{discord_id} - creates/links virtual user by Discord IDFormUser tkn-{token},{jwt_token} - user identification with JWT token (legacy)Bearer YOUR_TOKEN_HERE - recommended for API integrationsWhen using email: or discord_id: formats with FormUser tokens, the system automatically creates or reuses virtual users. Virtual users are accounts created on-the-fly for form submissions without requiring full user registration. This is useful for:
Virtual users created this way are marked as virtual accounts and work across Issues, Feature Requests, and Support Tickets.
Validation Rules:
email: format must match RFC 5322 email format. Invalid emails will fall back to anonymous access.discord_id: format must be numeric (digits only). Invalid discord_ids will fall back to anonymous access.Personal Access Tokens provide enhanced security and can be created and managed in your account settings. They are ideal for API integrations, automated scripts, and CI/CD pipelines. Tokens can have different permissions, including:
| Name | Type | Description |
|---|---|---|
| project_id required | string | |
| issue_id required | string |
| Name | Type | Description |
|---|---|---|
| BetaHub-Project-ID required | string | BetaHub project ID, the same as the project_id |
curl \ -X POST \ -H "Authorization: Bearer YOUR_API_TOKEN" \ -H "BetaHub-Project-ID: 123" \ -H "Content-Type: application/json" \ -d '{ "email": "user@example.com", "discord_id": "string" }' \ "https://app.betahub.io/projects/123/issues/g-123/set_contact_info"
require "net/http" require "json" uri = URI("https://app.betahub.io/projects/123/issues/g-123/set_contact_info") http = Net::HTTP.new(uri.host, uri.port) http.use_ssl = true request = Net::HTTP::Post.new(uri) request["Authorization"] = "Bearer YOUR_API_TOKEN" request["BetaHub-Project-ID"] = "123" request["Content-Type"] = "application/json" request.body = { "email": "user@example.com", "discord_id": "string" } response = http.request(request) puts response.body
import requests response = requests.post( "https://app.betahub.io/projects/123/issues/g-123/set_contact_info", headers={"Authorization": "Bearer YOUR_API_TOKEN", "BetaHub-Project-ID": "123"}, json={ "email": "user@example.com", "discord_id": "string" } ) print(response.json())
const response = await fetch("https://app.betahub.io/projects/123/issues/g-123/set_contact_info", { method: "POST", headers: { "Authorization": "Bearer YOUR_API_TOKEN", "BetaHub-Project-ID": "123", "Content-Type": "application/json" }, body: JSON.stringify({ "email": "user@example.com", "discord_id": "string" }) }); const data = await response.json();
HttpClient client = HttpClient.newHttpClient(); HttpRequest request = HttpRequest.newBuilder() .uri(URI.create("https://app.betahub.io/projects/123/issues/g-123/set_contact_info")) .header("Authorization", "Bearer YOUR_API_TOKEN") .header("BetaHub-Project-ID", "123") .header("Content-Type", "application/json") .POST(HttpRequest.BodyPublishers.ofString("{\"email\":\"user@example.com\",\"discord_id\":\"string\"}")) .build(); HttpResponse<String> response = client.send( request, HttpResponse.BodyHandlers.ofString()); System.out.println(response.body());
{
"email": "user@example.com",
"discord_id": "string"
}
{
"email": "reporter@example.com"
}
{
"error": "Invalid email format"
}
{
"error": "string",
"status": "string"
}
{
"error": "string",
"status": "string"
}
Authorization header for API access. Supports multiple authentication methods:
FormUser anonymous - for public operationsFormUser tkn-{token} - for authenticated operations with legacy tokensFormUser tkn-{token},email:{email} - creates/links virtual user by emailFormUser tkn-{token},discord_id:{discord_id} - creates/links virtual user by Discord IDFormUser tkn-{token},{jwt_token} - user identification with JWT token (legacy)Bearer YOUR_TOKEN_HERE - recommended for API integrationsWhen using email: or discord_id: formats with FormUser tokens, the system automatically creates or reuses virtual users. Virtual users are accounts created on-the-fly for form submissions without requiring full user registration. This is useful for:
Virtual users created this way are marked as virtual accounts and work across Issues, Feature Requests, and Support Tickets.
Validation Rules:
email: format must match RFC 5322 email format. Invalid emails will fall back to anonymous access.discord_id: format must be numeric (digits only). Invalid discord_ids will fall back to anonymous access.Personal Access Tokens provide enhanced security and can be created and managed in your account settings. They are ideal for API integrations, automated scripts, and CI/CD pipelines. Tokens can have different permissions, including:
| Name | Type | Description |
|---|---|---|
| project_id required | string | |
| issue_id required | string |
| Name | Type | Description |
|---|---|---|
| BetaHub-Project-ID required | string | BetaHub project ID, the same as the project_id |
curl \ -X POST \ -H "Authorization: Bearer YOUR_API_TOKEN" \ -H "BetaHub-Project-ID: 123" \ -H "Content-Type: application/json" \ -d '{ "email_my_report": true }' \ "https://app.betahub.io/projects/123/issues/g-123/publish"
require "net/http" require "json" uri = URI("https://app.betahub.io/projects/123/issues/g-123/publish") http = Net::HTTP.new(uri.host, uri.port) http.use_ssl = true request = Net::HTTP::Post.new(uri) request["Authorization"] = "Bearer YOUR_API_TOKEN" request["BetaHub-Project-ID"] = "123" request["Content-Type"] = "application/json" request.body = { "email_my_report": true } response = http.request(request) puts response.body
import requests response = requests.post( "https://app.betahub.io/projects/123/issues/g-123/publish", headers={"Authorization": "Bearer YOUR_API_TOKEN", "BetaHub-Project-ID": "123"}, json={ "email_my_report": true } ) print(response.json())
const response = await fetch("https://app.betahub.io/projects/123/issues/g-123/publish", { method: "POST", headers: { "Authorization": "Bearer YOUR_API_TOKEN", "BetaHub-Project-ID": "123", "Content-Type": "application/json" }, body: JSON.stringify({ "email_my_report": true }) }); const data = await response.json();
HttpClient client = HttpClient.newHttpClient(); HttpRequest request = HttpRequest.newBuilder() .uri(URI.create("https://app.betahub.io/projects/123/issues/g-123/publish")) .header("Authorization", "Bearer YOUR_API_TOKEN") .header("BetaHub-Project-ID", "123") .header("Content-Type", "application/json") .POST(HttpRequest.BodyPublishers.ofString("{\"email_my_report\":true}")) .build(); HttpResponse<String> response = client.send( request, HttpResponse.BodyHandlers.ofString()); System.out.println(response.body());
{
"email_my_report": true
}
{
"email_my_report": true
}
Authorization header for API access. Supports multiple authentication methods:
FormUser anonymous - for public operationsFormUser tkn-{token} - for authenticated operations with legacy tokensFormUser tkn-{token},email:{email} - creates/links virtual user by emailFormUser tkn-{token},discord_id:{discord_id} - creates/links virtual user by Discord IDFormUser tkn-{token},{jwt_token} - user identification with JWT token (legacy)Bearer YOUR_TOKEN_HERE - recommended for API integrationsWhen using email: or discord_id: formats with FormUser tokens, the system automatically creates or reuses virtual users. Virtual users are accounts created on-the-fly for form submissions without requiring full user registration. This is useful for:
Virtual users created this way are marked as virtual accounts and work across Issues, Feature Requests, and Support Tickets.
Validation Rules:
email: format must match RFC 5322 email format. Invalid emails will fall back to anonymous access.discord_id: format must be numeric (digits only). Invalid discord_ids will fall back to anonymous access.Personal Access Tokens provide enhanced security and can be created and managed in your account settings. They are ideal for API integrations, automated scripts, and CI/CD pipelines. Tokens can have different permissions, including:
| Name | Type | Description |
|---|---|---|
| project_id required | string | |
| issue_id required | string |
| Name | Type | Description |
|---|---|---|
| BetaHub-Project-ID required | string | BetaHub project ID, the same as the project_id |
curl \ -X POST \ -H "Authorization: Bearer YOUR_API_TOKEN" \ -H "BetaHub-Project-ID: 123" \ -H "Content-Type: application/json" \ -d '{ "what": "steps", "comment": "string" }' \ "https://app.betahub.io/projects/123/issues/g-123/ask_for_details"
require "net/http" require "json" uri = URI("https://app.betahub.io/projects/123/issues/g-123/ask_for_details") http = Net::HTTP.new(uri.host, uri.port) http.use_ssl = true request = Net::HTTP::Post.new(uri) request["Authorization"] = "Bearer YOUR_API_TOKEN" request["BetaHub-Project-ID"] = "123" request["Content-Type"] = "application/json" request.body = { "what": "steps", "comment": "string" } response = http.request(request) puts response.body
import requests response = requests.post( "https://app.betahub.io/projects/123/issues/g-123/ask_for_details", headers={"Authorization": "Bearer YOUR_API_TOKEN", "BetaHub-Project-ID": "123"}, json={ "what": "steps", "comment": "string" } ) print(response.json())
const response = await fetch("https://app.betahub.io/projects/123/issues/g-123/ask_for_details", { method: "POST", headers: { "Authorization": "Bearer YOUR_API_TOKEN", "BetaHub-Project-ID": "123", "Content-Type": "application/json" }, body: JSON.stringify({ "what": "steps", "comment": "string" }) }); const data = await response.json();
HttpClient client = HttpClient.newHttpClient(); HttpRequest request = HttpRequest.newBuilder() .uri(URI.create("https://app.betahub.io/projects/123/issues/g-123/ask_for_details")) .header("Authorization", "Bearer YOUR_API_TOKEN") .header("BetaHub-Project-ID", "123") .header("Content-Type", "application/json") .POST(HttpRequest.BodyPublishers.ofString("{\"what\":\"steps\",\"comment\":\"string\"}")) .build(); HttpResponse<String> response = client.send( request, HttpResponse.BodyHandlers.ofString()); System.out.println(response.body());
{
"what": "steps",
"comment": "string"
}
{
"what": "steps",
"comment": "Could you please provide detailed steps to reproduce this issue?"
}
{
"error": "Invalid request type"
}
{
"error": "string",
"status": "string"
}
{
"error": "string",
"status": "string"
}
Authorization header for API access. Supports multiple authentication methods:
FormUser anonymous - for public operationsFormUser tkn-{token} - for authenticated operations with legacy tokensFormUser tkn-{token},email:{email} - creates/links virtual user by emailFormUser tkn-{token},discord_id:{discord_id} - creates/links virtual user by Discord IDFormUser tkn-{token},{jwt_token} - user identification with JWT token (legacy)Bearer YOUR_TOKEN_HERE - recommended for API integrationsWhen using email: or discord_id: formats with FormUser tokens, the system automatically creates or reuses virtual users. Virtual users are accounts created on-the-fly for form submissions without requiring full user registration. This is useful for:
Virtual users created this way are marked as virtual accounts and work across Issues, Feature Requests, and Support Tickets.
Validation Rules:
email: format must match RFC 5322 email format. Invalid emails will fall back to anonymous access.discord_id: format must be numeric (digits only). Invalid discord_ids will fall back to anonymous access.Personal Access Tokens provide enhanced security and can be created and managed in your account settings. They are ideal for API integrations, automated scripts, and CI/CD pipelines. Tokens can have different permissions, including:
| Name | Type | Description |
|---|---|---|
| project_id required | string | |
| issue_id required | string |
| Name | Type | Description |
|---|---|---|
| BetaHub-Project-ID required | string | BetaHub project ID, the same as the project_id |
curl \ -H "Authorization: Bearer YOUR_API_TOKEN" \ -H "BetaHub-Project-ID: 123" \ "https://app.betahub.io/projects/123/issues/g-123/screenshots"
require "net/http" uri = URI("https://app.betahub.io/projects/123/issues/g-123/screenshots") http = Net::HTTP.new(uri.host, uri.port) http.use_ssl = true request = Net::HTTP::Get.new(uri) request["Authorization"] = "Bearer YOUR_API_TOKEN" request["BetaHub-Project-ID"] = "123" response = http.request(request) puts response.body
import requests response = requests.get( "https://app.betahub.io/projects/123/issues/g-123/screenshots", headers={"Authorization": "Bearer YOUR_API_TOKEN", "BetaHub-Project-ID": "123"} ) print(response.json())
const response = await fetch("https://app.betahub.io/projects/123/issues/g-123/screenshots", { headers: { "Authorization": "Bearer YOUR_API_TOKEN", "BetaHub-Project-ID": "123" } }); const data = await response.json();
HttpClient client = HttpClient.newHttpClient(); HttpRequest request = HttpRequest.newBuilder() .uri(URI.create("https://app.betahub.io/projects/123/issues/g-123/screenshots")) .header("Authorization", "Bearer YOUR_API_TOKEN") .header("BetaHub-Project-ID", "123") .GET() .build(); HttpResponse<String> response = client.send( request, HttpResponse.BodyHandlers.ofString()); System.out.println(response.body());
[
{
"id": 0,
"type": "screenshot",
"description": "string",
"size_bytes": 0,
"media_size_bytes": 0,
"content_type": "string",
"url": "https://example.com",
"filename": "string",
"layer_a_url": "https://example.com",
"layer_a_filename": "string",
"created_at": "2026-03-12T10:30:00Z",
"updated_at": "2026-03-12T10:30:00Z",
"user": {
"id": 0,
"name": "string"
}
}
]
{
"error": "string",
"status": "string"
}
Authorization header for API access. Supports multiple authentication methods:
FormUser anonymous - for public operationsFormUser tkn-{token} - for authenticated operations with legacy tokensFormUser tkn-{token},email:{email} - creates/links virtual user by emailFormUser tkn-{token},discord_id:{discord_id} - creates/links virtual user by Discord IDFormUser tkn-{token},{jwt_token} - user identification with JWT token (legacy)Bearer YOUR_TOKEN_HERE - recommended for API integrationsWhen using email: or discord_id: formats with FormUser tokens, the system automatically creates or reuses virtual users. Virtual users are accounts created on-the-fly for form submissions without requiring full user registration. This is useful for:
Virtual users created this way are marked as virtual accounts and work across Issues, Feature Requests, and Support Tickets.
Validation Rules:
email: format must match RFC 5322 email format. Invalid emails will fall back to anonymous access.discord_id: format must be numeric (digits only). Invalid discord_ids will fall back to anonymous access.Personal Access Tokens provide enhanced security and can be created and managed in your account settings. They are ideal for API integrations, automated scripts, and CI/CD pipelines. Tokens can have different permissions, including:
| Name | Type | Description |
|---|---|---|
| project_id required | string | |
| issue_id required | string |
| Name | Type | Description |
|---|---|---|
| BetaHub-Project-ID required | string | BetaHub project ID, the same as the project_id |
curl \ -X POST \ -H "Authorization: Bearer YOUR_API_TOKEN" \ -H "BetaHub-Project-ID: 123" \ -F "screenshot[image]=@file.bin" \ -F "screenshot[name]=string" \ "https://app.betahub.io/projects/123/issues/g-123/screenshots"
require "net/http" require "json" uri = URI("https://app.betahub.io/projects/123/issues/g-123/screenshots") http = Net::HTTP.new(uri.host, uri.port) http.use_ssl = true request = Net::HTTP::Post.new(uri) request["Authorization"] = "Bearer YOUR_API_TOKEN" request["BetaHub-Project-ID"] = "123" response = http.request(request) puts response.body
import requests response = requests.post( "https://app.betahub.io/projects/123/issues/g-123/screenshots", headers={"Authorization": "Bearer YOUR_API_TOKEN", "BetaHub-Project-ID": "123"} ) print(response.json())
const response = await fetch("https://app.betahub.io/projects/123/issues/g-123/screenshots", { method: "POST", headers: { "Authorization": "Bearer YOUR_API_TOKEN", "BetaHub-Project-ID": "123" } }); const data = await response.json();
HttpClient client = HttpClient.newHttpClient(); HttpRequest request = HttpRequest.newBuilder() .uri(URI.create("https://app.betahub.io/projects/123/issues/g-123/screenshots")) .header("Authorization", "Bearer YOUR_API_TOKEN") .header("BetaHub-Project-ID", "123") .header("Content-Type", "application/json") .POST(HttpRequest.BodyPublishers.ofString("{\"screenshot[image]\":\"string\",\"screenshot[name]\":\"string\"}")) .build(); HttpResponse<String> response = client.send( request, HttpResponse.BodyHandlers.ofString()); System.out.println(response.body());
{
"screenshot[image]": "string",
"screenshot[name]": "string"
}
{
"screenshot[image]": "(binary data representing an image)"
}
| Name | Type | Description |
|---|---|---|
| project_id required | string | |
| issue_id required | string |
curl \ -X POST \ -H "Authorization: Bearer YOUR_API_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "filename": "screenshot.png", "byte_size": 1048576, "checksum": "1B2M2Y8AsgTpgAmY7PhCfg==", "content_type": "image/png", "name": "Player Death Screenshot" }' \ "https://app.betahub.io/projects/123/issues/g-123/screenshots/presigned_upload"
require "net/http" require "json" uri = URI("https://app.betahub.io/projects/123/issues/g-123/screenshots/presigned_upload") http = Net::HTTP.new(uri.host, uri.port) http.use_ssl = true request = Net::HTTP::Post.new(uri) request["Authorization"] = "Bearer YOUR_API_TOKEN" request["Content-Type"] = "application/json" request.body = { "filename": "screenshot.png", "byte_size": 1048576, "checksum": "1B2M2Y8AsgTpgAmY7PhCfg==", "content_type": "image/png", "name": "Player Death Screenshot" } response = http.request(request) puts response.body
import requests response = requests.post( "https://app.betahub.io/projects/123/issues/g-123/screenshots/presigned_upload", headers={"Authorization": "Bearer YOUR_API_TOKEN"}, json={ "filename": "screenshot.png", "byte_size": 1048576, "checksum": "1B2M2Y8AsgTpgAmY7PhCfg==", "content_type": "image/png", "name": "Player Death Screenshot" } ) print(response.json())
const response = await fetch("https://app.betahub.io/projects/123/issues/g-123/screenshots/presigned_upload", { method: "POST", headers: { "Authorization": "Bearer YOUR_API_TOKEN", "Content-Type": "application/json" }, body: JSON.stringify({ "filename": "screenshot.png", "byte_size": 1048576, "checksum": "1B2M2Y8AsgTpgAmY7PhCfg==", "content_type": "image/png", "name": "Player Death Screenshot" }) }); const data = await response.json();
HttpClient client = HttpClient.newHttpClient(); HttpRequest request = HttpRequest.newBuilder() .uri(URI.create("https://app.betahub.io/projects/123/issues/g-123/screenshots/presigned_upload")) .header("Authorization", "Bearer YOUR_API_TOKEN") .header("Content-Type", "application/json") .POST(HttpRequest.BodyPublishers.ofString("{\"filename\":\"screenshot.png\",\"byte_size\":1048576,\"checksum\":\"1B2M2Y8AsgTpgAmY7PhCfg==\",\"content_type\":\"image/png\",\"name\":\"Player Death Screenshot\"}")) .build(); HttpResponse<String> response = client.send( request, HttpResponse.BodyHandlers.ofString()); System.out.println(response.body());
{
"filename": "screenshot.png",
"byte_size": 1048576,
"checksum": "1B2M2Y8AsgTpgAmY7PhCfg==",
"content_type": "image/png",
"name": "Player Death Screenshot"
}
{
"blob_signed_id": "string",
"direct_upload_url": "https://example.com",
"headers": {},
"blob_id": 0
}
{
"errors": [
"string"
],
"message": "string"
}
{
"error": "string",
"status": "string"
}
| Name | Type | Description |
|---|---|---|
| project_id required | string | |
| issue_id required | string |
curl \ -X POST \ -H "Authorization: Bearer YOUR_API_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "blob_signed_id": "string", "name": "Player Death Screenshot" }' \ "https://app.betahub.io/projects/123/issues/g-123/screenshots/confirm_upload"
require "net/http" require "json" uri = URI("https://app.betahub.io/projects/123/issues/g-123/screenshots/confirm_upload") http = Net::HTTP.new(uri.host, uri.port) http.use_ssl = true request = Net::HTTP::Post.new(uri) request["Authorization"] = "Bearer YOUR_API_TOKEN" request["Content-Type"] = "application/json" request.body = { "blob_signed_id": "string", "name": "Player Death Screenshot" } response = http.request(request) puts response.body
import requests response = requests.post( "https://app.betahub.io/projects/123/issues/g-123/screenshots/confirm_upload", headers={"Authorization": "Bearer YOUR_API_TOKEN"}, json={ "blob_signed_id": "string", "name": "Player Death Screenshot" } ) print(response.json())
const response = await fetch("https://app.betahub.io/projects/123/issues/g-123/screenshots/confirm_upload", { method: "POST", headers: { "Authorization": "Bearer YOUR_API_TOKEN", "Content-Type": "application/json" }, body: JSON.stringify({ "blob_signed_id": "string", "name": "Player Death Screenshot" }) }); const data = await response.json();
HttpClient client = HttpClient.newHttpClient(); HttpRequest request = HttpRequest.newBuilder() .uri(URI.create("https://app.betahub.io/projects/123/issues/g-123/screenshots/confirm_upload")) .header("Authorization", "Bearer YOUR_API_TOKEN") .header("Content-Type", "application/json") .POST(HttpRequest.BodyPublishers.ofString("{\"blob_signed_id\":\"string\",\"name\":\"Player Death Screenshot\"}")) .build(); HttpResponse<String> response = client.send( request, HttpResponse.BodyHandlers.ofString()); System.out.println(response.body());
{
"blob_signed_id": "string",
"name": "Player Death Screenshot"
}
{
"id": "string",
"created_at": "2026-03-12T10:30:00Z",
"updated_at": "2026-03-12T10:30:00Z",
"status": "string",
"description": "string",
"issue_id": "string",
"image_url": "https://example.com"
}
{
"errors": [
"string"
],
"message": "string"
}
{
"error": "string",
"status": "string"
}
Authorization header for API access. Supports multiple authentication methods:
FormUser anonymous - for public operationsFormUser tkn-{token} - for authenticated operations with legacy tokensFormUser tkn-{token},email:{email} - creates/links virtual user by emailFormUser tkn-{token},discord_id:{discord_id} - creates/links virtual user by Discord IDFormUser tkn-{token},{jwt_token} - user identification with JWT token (legacy)Bearer YOUR_TOKEN_HERE - recommended for API integrationsWhen using email: or discord_id: formats with FormUser tokens, the system automatically creates or reuses virtual users. Virtual users are accounts created on-the-fly for form submissions without requiring full user registration. This is useful for:
Virtual users created this way are marked as virtual accounts and work across Issues, Feature Requests, and Support Tickets.
Validation Rules:
email: format must match RFC 5322 email format. Invalid emails will fall back to anonymous access.discord_id: format must be numeric (digits only). Invalid discord_ids will fall back to anonymous access.Personal Access Tokens provide enhanced security and can be created and managed in your account settings. They are ideal for API integrations, automated scripts, and CI/CD pipelines. Tokens can have different permissions, including:
| Name | Type | Description |
|---|---|---|
| project_id required | string | |
| issue_id required | string |
| Name | Type | Description |
|---|---|---|
| BetaHub-Project-ID required | string | BetaHub project ID, the same as the project_id |
curl \ -H "Authorization: Bearer YOUR_API_TOKEN" \ -H "BetaHub-Project-ID: 123" \ "https://app.betahub.io/projects/123/issues/g-123/log_files"
require "net/http" uri = URI("https://app.betahub.io/projects/123/issues/g-123/log_files") http = Net::HTTP.new(uri.host, uri.port) http.use_ssl = true request = Net::HTTP::Get.new(uri) request["Authorization"] = "Bearer YOUR_API_TOKEN" request["BetaHub-Project-ID"] = "123" response = http.request(request) puts response.body
import requests response = requests.get( "https://app.betahub.io/projects/123/issues/g-123/log_files", headers={"Authorization": "Bearer YOUR_API_TOKEN", "BetaHub-Project-ID": "123"} ) print(response.json())
const response = await fetch("https://app.betahub.io/projects/123/issues/g-123/log_files", { headers: { "Authorization": "Bearer YOUR_API_TOKEN", "BetaHub-Project-ID": "123" } }); const data = await response.json();
HttpClient client = HttpClient.newHttpClient(); HttpRequest request = HttpRequest.newBuilder() .uri(URI.create("https://app.betahub.io/projects/123/issues/g-123/log_files")) .header("Authorization", "Bearer YOUR_API_TOKEN") .header("BetaHub-Project-ID", "123") .GET() .build(); HttpResponse<String> response = client.send( request, HttpResponse.BodyHandlers.ofString()); System.out.println(response.body());
[
{
"id": 0,
"created_at": "2026-03-12T10:30:00Z",
"updated_at": "2026-03-12T10:30:00Z",
"media_size_bytes": 0,
"type": "log_file",
"size_bytes": 0,
"content_type": "text/plain",
"url": "https://example.com",
"filename": "string",
"user": {
"id": 0,
"name": "string"
}
}
]
{
"error": "string",
"status": "string"
}
Upload a log file to an issue. Supports two methods:
Method 1: File upload — Send the file as multipart/form-data with log_file[file] field.
Method 2: Text content — Send log contents as a string via application/json,
application/x-www-form-urlencoded, or multipart/form-data using the log_file[contents] field.
The text will be stored as a .txt file. This is useful for clients that cannot perform file uploads
(e.g., game engines with limited HTTP support).
Both methods support the optional log_file[name] field to set a custom filename.
Authorization header for API access. Supports multiple authentication methods:
FormUser anonymous - for public operationsFormUser tkn-{token} - for authenticated operations with legacy tokensFormUser tkn-{token},email:{email} - creates/links virtual user by emailFormUser tkn-{token},discord_id:{discord_id} - creates/links virtual user by Discord IDFormUser tkn-{token},{jwt_token} - user identification with JWT token (legacy)Bearer YOUR_TOKEN_HERE - recommended for API integrationsWhen using email: or discord_id: formats with FormUser tokens, the system automatically creates or reuses virtual users. Virtual users are accounts created on-the-fly for form submissions without requiring full user registration. This is useful for:
Virtual users created this way are marked as virtual accounts and work across Issues, Feature Requests, and Support Tickets.
Validation Rules:
email: format must match RFC 5322 email format. Invalid emails will fall back to anonymous access.discord_id: format must be numeric (digits only). Invalid discord_ids will fall back to anonymous access.Personal Access Tokens provide enhanced security and can be created and managed in your account settings. They are ideal for API integrations, automated scripts, and CI/CD pipelines. Tokens can have different permissions, including:
| Name | Type | Description |
|---|---|---|
| project_id required | string | |
| issue_id required | string |
| Name | Type | Description |
|---|---|---|
| BetaHub-Project-ID required | string | BetaHub project ID, the same as the project_id |
log_file[contents] is provided.
log_file[file] when file uploads are not possible. The text will be stored as a text/plain file.
curl \ -X POST \ -H "Authorization: Bearer YOUR_API_TOKEN" \ -H "BetaHub-Project-ID: 123" \ -F "log_file[file]=@file.bin" \ -F "log_file[contents]=@file.bin" \ -F "log_file[name]=@file.bin" \ "https://app.betahub.io/projects/123/issues/g-123/log_files"
require "net/http" require "json" uri = URI("https://app.betahub.io/projects/123/issues/g-123/log_files") http = Net::HTTP.new(uri.host, uri.port) http.use_ssl = true request = Net::HTTP::Post.new(uri) request["Authorization"] = "Bearer YOUR_API_TOKEN" request["BetaHub-Project-ID"] = "123" response = http.request(request) puts response.body
import requests response = requests.post( "https://app.betahub.io/projects/123/issues/g-123/log_files", headers={"Authorization": "Bearer YOUR_API_TOKEN", "BetaHub-Project-ID": "123"} ) print(response.json())
const response = await fetch("https://app.betahub.io/projects/123/issues/g-123/log_files", { method: "POST", headers: { "Authorization": "Bearer YOUR_API_TOKEN", "BetaHub-Project-ID": "123" } }); const data = await response.json();
HttpClient client = HttpClient.newHttpClient(); HttpRequest request = HttpRequest.newBuilder() .uri(URI.create("https://app.betahub.io/projects/123/issues/g-123/log_files")) .header("Authorization", "Bearer YOUR_API_TOKEN") .header("BetaHub-Project-ID", "123") .header("Content-Type", "application/json") .POST(HttpRequest.BodyPublishers.ofString("{\"log_file[file]\":\"string\",\"log_file[contents]\":\"string\",\"log_file[name]\":\"string\"}")) .build(); HttpResponse<String> response = client.send( request, HttpResponse.BodyHandlers.ofString()); System.out.println(response.body());
{
"log_file[file]": "string",
"log_file[contents]": "string",
"log_file[name]": "string"
}
{
"id": 0,
"created_at": "2026-03-12T10:30:00Z",
"updated_at": "2026-03-12T10:30:00Z",
"media_size_bytes": 0,
"type": "log_file",
"size_bytes": 0,
"content_type": "text/plain",
"url": "https://example.com",
"filename": "string",
"user": {
"id": 0,
"name": "string"
}
}
{
"errors": [
"string"
],
"message": "string"
}
{
"error": "string",
"status": "string"
}
| Name | Type | Description |
|---|---|---|
| project_id required | string | |
| issue_id required | string |
curl \ -X POST \ -H "Authorization: Bearer YOUR_API_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "filename": "application.log", "byte_size": 2048000, "checksum": "1B2M2Y8AsgTpgAmY7PhCfg==", "content_type": "text/plain", "name": "Debug Log" }' \ "https://app.betahub.io/projects/123/issues/g-123/log_files/presigned_upload"
require "net/http" require "json" uri = URI("https://app.betahub.io/projects/123/issues/g-123/log_files/presigned_upload") http = Net::HTTP.new(uri.host, uri.port) http.use_ssl = true request = Net::HTTP::Post.new(uri) request["Authorization"] = "Bearer YOUR_API_TOKEN" request["Content-Type"] = "application/json" request.body = { "filename": "application.log", "byte_size": 2048000, "checksum": "1B2M2Y8AsgTpgAmY7PhCfg==", "content_type": "text/plain", "name": "Debug Log" } response = http.request(request) puts response.body
import requests response = requests.post( "https://app.betahub.io/projects/123/issues/g-123/log_files/presigned_upload", headers={"Authorization": "Bearer YOUR_API_TOKEN"}, json={ "filename": "application.log", "byte_size": 2048000, "checksum": "1B2M2Y8AsgTpgAmY7PhCfg==", "content_type": "text/plain", "name": "Debug Log" } ) print(response.json())
const response = await fetch("https://app.betahub.io/projects/123/issues/g-123/log_files/presigned_upload", { method: "POST", headers: { "Authorization": "Bearer YOUR_API_TOKEN", "Content-Type": "application/json" }, body: JSON.stringify({ "filename": "application.log", "byte_size": 2048000, "checksum": "1B2M2Y8AsgTpgAmY7PhCfg==", "content_type": "text/plain", "name": "Debug Log" }) }); const data = await response.json();
HttpClient client = HttpClient.newHttpClient(); HttpRequest request = HttpRequest.newBuilder() .uri(URI.create("https://app.betahub.io/projects/123/issues/g-123/log_files/presigned_upload")) .header("Authorization", "Bearer YOUR_API_TOKEN") .header("Content-Type", "application/json") .POST(HttpRequest.BodyPublishers.ofString("{\"filename\":\"application.log\",\"byte_size\":2048000,\"checksum\":\"1B2M2Y8AsgTpgAmY7PhCfg==\",\"content_type\":\"text/plain\",\"name\":\"Debug Log\"}")) .build(); HttpResponse<String> response = client.send( request, HttpResponse.BodyHandlers.ofString()); System.out.println(response.body());
{
"filename": "application.log",
"byte_size": 2048000,
"checksum": "1B2M2Y8AsgTpgAmY7PhCfg==",
"content_type": "text/plain",
"name": "Debug Log"
}
{
"blob_signed_id": "string",
"direct_upload_url": "https://example.com",
"headers": {},
"blob_id": 0
}
{
"errors": [
"string"
],
"message": "string"
}
{
"error": "string",
"status": "string"
}
| Name | Type | Description |
|---|---|---|
| project_id required | string | |
| issue_id required | string |
curl \ -X POST \ -H "Authorization: Bearer YOUR_API_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "blob_signed_id": "string", "name": "Debug Log" }' \ "https://app.betahub.io/projects/123/issues/g-123/log_files/confirm_upload"
require "net/http" require "json" uri = URI("https://app.betahub.io/projects/123/issues/g-123/log_files/confirm_upload") http = Net::HTTP.new(uri.host, uri.port) http.use_ssl = true request = Net::HTTP::Post.new(uri) request["Authorization"] = "Bearer YOUR_API_TOKEN" request["Content-Type"] = "application/json" request.body = { "blob_signed_id": "string", "name": "Debug Log" } response = http.request(request) puts response.body
import requests response = requests.post( "https://app.betahub.io/projects/123/issues/g-123/log_files/confirm_upload", headers={"Authorization": "Bearer YOUR_API_TOKEN"}, json={ "blob_signed_id": "string", "name": "Debug Log" } ) print(response.json())
const response = await fetch("https://app.betahub.io/projects/123/issues/g-123/log_files/confirm_upload", { method: "POST", headers: { "Authorization": "Bearer YOUR_API_TOKEN", "Content-Type": "application/json" }, body: JSON.stringify({ "blob_signed_id": "string", "name": "Debug Log" }) }); const data = await response.json();
HttpClient client = HttpClient.newHttpClient(); HttpRequest request = HttpRequest.newBuilder() .uri(URI.create("https://app.betahub.io/projects/123/issues/g-123/log_files/confirm_upload")) .header("Authorization", "Bearer YOUR_API_TOKEN") .header("Content-Type", "application/json") .POST(HttpRequest.BodyPublishers.ofString("{\"blob_signed_id\":\"string\",\"name\":\"Debug Log\"}")) .build(); HttpResponse<String> response = client.send( request, HttpResponse.BodyHandlers.ofString()); System.out.println(response.body());
{
"blob_signed_id": "string",
"name": "Debug Log"
}
{
"id": 0,
"created_at": "2026-03-12T10:30:00Z",
"updated_at": "2026-03-12T10:30:00Z",
"media_size_bytes": 0,
"type": "log_file",
"size_bytes": 0,
"content_type": "text/plain",
"url": "https://example.com",
"filename": "string",
"user": {
"id": 0,
"name": "string"
}
}
{
"errors": [
"string"
],
"message": "string"
}
{
"error": "string",
"status": "string"
}
Authorization header for API access. Supports multiple authentication methods:
FormUser anonymous - for public operationsFormUser tkn-{token} - for authenticated operations with legacy tokensFormUser tkn-{token},email:{email} - creates/links virtual user by emailFormUser tkn-{token},discord_id:{discord_id} - creates/links virtual user by Discord IDFormUser tkn-{token},{jwt_token} - user identification with JWT token (legacy)Bearer YOUR_TOKEN_HERE - recommended for API integrationsWhen using email: or discord_id: formats with FormUser tokens, the system automatically creates or reuses virtual users. Virtual users are accounts created on-the-fly for form submissions without requiring full user registration. This is useful for:
Virtual users created this way are marked as virtual accounts and work across Issues, Feature Requests, and Support Tickets.
Validation Rules:
email: format must match RFC 5322 email format. Invalid emails will fall back to anonymous access.discord_id: format must be numeric (digits only). Invalid discord_ids will fall back to anonymous access.Personal Access Tokens provide enhanced security and can be created and managed in your account settings. They are ideal for API integrations, automated scripts, and CI/CD pipelines. Tokens can have different permissions, including:
| Name | Type | Description |
|---|---|---|
| project_id required | string | |
| issue_id required | string |
| Name | Type | Description |
|---|---|---|
| BetaHub-Project-ID required | string | BetaHub project ID, the same as the project_id |
curl \ -H "Authorization: Bearer YOUR_API_TOKEN" \ -H "BetaHub-Project-ID: 123" \ "https://app.betahub.io/projects/123/issues/g-123/binary_files"
require "net/http" uri = URI("https://app.betahub.io/projects/123/issues/g-123/binary_files") http = Net::HTTP.new(uri.host, uri.port) http.use_ssl = true request = Net::HTTP::Get.new(uri) request["Authorization"] = "Bearer YOUR_API_TOKEN" request["BetaHub-Project-ID"] = "123" response = http.request(request) puts response.body
import requests response = requests.get( "https://app.betahub.io/projects/123/issues/g-123/binary_files", headers={"Authorization": "Bearer YOUR_API_TOKEN", "BetaHub-Project-ID": "123"} ) print(response.json())
const response = await fetch("https://app.betahub.io/projects/123/issues/g-123/binary_files", { headers: { "Authorization": "Bearer YOUR_API_TOKEN", "BetaHub-Project-ID": "123" } }); const data = await response.json();
HttpClient client = HttpClient.newHttpClient(); HttpRequest request = HttpRequest.newBuilder() .uri(URI.create("https://app.betahub.io/projects/123/issues/g-123/binary_files")) .header("Authorization", "Bearer YOUR_API_TOKEN") .header("BetaHub-Project-ID", "123") .GET() .build(); HttpResponse<String> response = client.send( request, HttpResponse.BodyHandlers.ofString()); System.out.println(response.body());
[
{
"id": 0,
"created_at": "2026-03-12T10:30:00Z",
"updated_at": "2026-03-12T10:30:00Z",
"media_size_bytes": 0,
"type": "binary_file",
"size_bytes": 0,
"content_type": "application/octet-stream",
"url": "https://example.com",
"filename": "string",
"user": {
"id": 0,
"name": "string"
}
}
]
{
"error": "string",
"status": "string"
}
Upload a binary file to an issue using multipart/form-data with binary_file[file] field.
The optional binary_file[name] field can be used to set a custom filename.
Authorization header for API access. Supports multiple authentication methods:
FormUser anonymous - for public operationsFormUser tkn-{token} - for authenticated operations with legacy tokensFormUser tkn-{token},email:{email} - creates/links virtual user by emailFormUser tkn-{token},discord_id:{discord_id} - creates/links virtual user by Discord IDFormUser tkn-{token},{jwt_token} - user identification with JWT token (legacy)Bearer YOUR_TOKEN_HERE - recommended for API integrationsWhen using email: or discord_id: formats with FormUser tokens, the system automatically creates or reuses virtual users. Virtual users are accounts created on-the-fly for form submissions without requiring full user registration. This is useful for:
Virtual users created this way are marked as virtual accounts and work across Issues, Feature Requests, and Support Tickets.
Validation Rules:
email: format must match RFC 5322 email format. Invalid emails will fall back to anonymous access.discord_id: format must be numeric (digits only). Invalid discord_ids will fall back to anonymous access.Personal Access Tokens provide enhanced security and can be created and managed in your account settings. They are ideal for API integrations, automated scripts, and CI/CD pipelines. Tokens can have different permissions, including:
| Name | Type | Description |
|---|---|---|
| project_id required | string | |
| issue_id required | string |
| Name | Type | Description |
|---|---|---|
| BetaHub-Project-ID required | string | BetaHub project ID, the same as the project_id |
curl \ -X POST \ -H "Authorization: Bearer YOUR_API_TOKEN" \ -H "BetaHub-Project-ID: 123" \ -F "binary_file[file]=@file.bin" \ -F "binary_file[name]=@file.bin" \ "https://app.betahub.io/projects/123/issues/g-123/binary_files"
require "net/http" require "json" uri = URI("https://app.betahub.io/projects/123/issues/g-123/binary_files") http = Net::HTTP.new(uri.host, uri.port) http.use_ssl = true request = Net::HTTP::Post.new(uri) request["Authorization"] = "Bearer YOUR_API_TOKEN" request["BetaHub-Project-ID"] = "123" response = http.request(request) puts response.body
import requests response = requests.post( "https://app.betahub.io/projects/123/issues/g-123/binary_files", headers={"Authorization": "Bearer YOUR_API_TOKEN", "BetaHub-Project-ID": "123"} ) print(response.json())
const response = await fetch("https://app.betahub.io/projects/123/issues/g-123/binary_files", { method: "POST", headers: { "Authorization": "Bearer YOUR_API_TOKEN", "BetaHub-Project-ID": "123" } }); const data = await response.json();
HttpClient client = HttpClient.newHttpClient(); HttpRequest request = HttpRequest.newBuilder() .uri(URI.create("https://app.betahub.io/projects/123/issues/g-123/binary_files")) .header("Authorization", "Bearer YOUR_API_TOKEN") .header("BetaHub-Project-ID", "123") .header("Content-Type", "application/json") .POST(HttpRequest.BodyPublishers.ofString("{\"binary_file[file]\":\"string\",\"binary_file[name]\":\"string\"}")) .build(); HttpResponse<String> response = client.send( request, HttpResponse.BodyHandlers.ofString()); System.out.println(response.body());
{
"binary_file[file]": "string",
"binary_file[name]": "string"
}
{
"id": 0,
"created_at": "2026-03-12T10:30:00Z",
"updated_at": "2026-03-12T10:30:00Z",
"media_size_bytes": 0,
"type": "binary_file",
"size_bytes": 0,
"content_type": "application/octet-stream",
"url": "https://example.com",
"filename": "string",
"user": {
"id": 0,
"name": "string"
}
}
{
"errors": [
"string"
],
"message": "string"
}
{
"error": "string",
"status": "string"
}
| Name | Type | Description |
|---|---|---|
| project_id required | string | |
| issue_id required | string |
curl \ -X POST \ -H "Authorization: Bearer YOUR_API_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "filename": "crashdump.bin", "byte_size": 2048000, "checksum": "1B2M2Y8AsgTpgAmY7PhCfg==", "content_type": "application/octet-stream", "name": "Crash Dump" }' \ "https://app.betahub.io/projects/123/issues/g-123/binary_files/presigned_upload"
require "net/http" require "json" uri = URI("https://app.betahub.io/projects/123/issues/g-123/binary_files/presigned_upload") http = Net::HTTP.new(uri.host, uri.port) http.use_ssl = true request = Net::HTTP::Post.new(uri) request["Authorization"] = "Bearer YOUR_API_TOKEN" request["Content-Type"] = "application/json" request.body = { "filename": "crashdump.bin", "byte_size": 2048000, "checksum": "1B2M2Y8AsgTpgAmY7PhCfg==", "content_type": "application/octet-stream", "name": "Crash Dump" } response = http.request(request) puts response.body
import requests response = requests.post( "https://app.betahub.io/projects/123/issues/g-123/binary_files/presigned_upload", headers={"Authorization": "Bearer YOUR_API_TOKEN"}, json={ "filename": "crashdump.bin", "byte_size": 2048000, "checksum": "1B2M2Y8AsgTpgAmY7PhCfg==", "content_type": "application/octet-stream", "name": "Crash Dump" } ) print(response.json())
const response = await fetch("https://app.betahub.io/projects/123/issues/g-123/binary_files/presigned_upload", { method: "POST", headers: { "Authorization": "Bearer YOUR_API_TOKEN", "Content-Type": "application/json" }, body: JSON.stringify({ "filename": "crashdump.bin", "byte_size": 2048000, "checksum": "1B2M2Y8AsgTpgAmY7PhCfg==", "content_type": "application/octet-stream", "name": "Crash Dump" }) }); const data = await response.json();
HttpClient client = HttpClient.newHttpClient(); HttpRequest request = HttpRequest.newBuilder() .uri(URI.create("https://app.betahub.io/projects/123/issues/g-123/binary_files/presigned_upload")) .header("Authorization", "Bearer YOUR_API_TOKEN") .header("Content-Type", "application/json") .POST(HttpRequest.BodyPublishers.ofString("{\"filename\":\"crashdump.bin\",\"byte_size\":2048000,\"checksum\":\"1B2M2Y8AsgTpgAmY7PhCfg==\",\"content_type\":\"application/octet-stream\",\"name\":\"Crash Dump\"}")) .build(); HttpResponse<String> response = client.send( request, HttpResponse.BodyHandlers.ofString()); System.out.println(response.body());
{
"filename": "crashdump.bin",
"byte_size": 2048000,
"checksum": "1B2M2Y8AsgTpgAmY7PhCfg==",
"content_type": "application/octet-stream",
"name": "Crash Dump"
}
{
"blob_signed_id": "string",
"direct_upload_url": "https://example.com",
"headers": {},
"blob_id": 0
}
{
"errors": [
"string"
],
"message": "string"
}
{
"error": "string",
"status": "string"
}
| Name | Type | Description |
|---|---|---|
| project_id required | string | |
| issue_id required | string |
curl \ -X POST \ -H "Authorization: Bearer YOUR_API_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "blob_signed_id": "string", "name": "Crash Dump" }' \ "https://app.betahub.io/projects/123/issues/g-123/binary_files/confirm_upload"
require "net/http" require "json" uri = URI("https://app.betahub.io/projects/123/issues/g-123/binary_files/confirm_upload") http = Net::HTTP.new(uri.host, uri.port) http.use_ssl = true request = Net::HTTP::Post.new(uri) request["Authorization"] = "Bearer YOUR_API_TOKEN" request["Content-Type"] = "application/json" request.body = { "blob_signed_id": "string", "name": "Crash Dump" } response = http.request(request) puts response.body
import requests response = requests.post( "https://app.betahub.io/projects/123/issues/g-123/binary_files/confirm_upload", headers={"Authorization": "Bearer YOUR_API_TOKEN"}, json={ "blob_signed_id": "string", "name": "Crash Dump" } ) print(response.json())
const response = await fetch("https://app.betahub.io/projects/123/issues/g-123/binary_files/confirm_upload", { method: "POST", headers: { "Authorization": "Bearer YOUR_API_TOKEN", "Content-Type": "application/json" }, body: JSON.stringify({ "blob_signed_id": "string", "name": "Crash Dump" }) }); const data = await response.json();
HttpClient client = HttpClient.newHttpClient(); HttpRequest request = HttpRequest.newBuilder() .uri(URI.create("https://app.betahub.io/projects/123/issues/g-123/binary_files/confirm_upload")) .header("Authorization", "Bearer YOUR_API_TOKEN") .header("Content-Type", "application/json") .POST(HttpRequest.BodyPublishers.ofString("{\"blob_signed_id\":\"string\",\"name\":\"Crash Dump\"}")) .build(); HttpResponse<String> response = client.send( request, HttpResponse.BodyHandlers.ofString()); System.out.println(response.body());
{
"blob_signed_id": "string",
"name": "Crash Dump"
}
{
"id": 0,
"created_at": "2026-03-12T10:30:00Z",
"updated_at": "2026-03-12T10:30:00Z",
"media_size_bytes": 0,
"type": "binary_file",
"size_bytes": 0,
"content_type": "application/octet-stream",
"url": "https://example.com",
"filename": "string",
"user": {
"id": 0,
"name": "string"
}
}
{
"errors": [
"string"
],
"message": "string"
}
{
"error": "string",
"status": "string"
}
Authorization header for API access. Supports multiple authentication methods:
FormUser anonymous - for public operationsFormUser tkn-{token} - for authenticated operations with legacy tokensFormUser tkn-{token},email:{email} - creates/links virtual user by emailFormUser tkn-{token},discord_id:{discord_id} - creates/links virtual user by Discord IDFormUser tkn-{token},{jwt_token} - user identification with JWT token (legacy)Bearer YOUR_TOKEN_HERE - recommended for API integrationsWhen using email: or discord_id: formats with FormUser tokens, the system automatically creates or reuses virtual users. Virtual users are accounts created on-the-fly for form submissions without requiring full user registration. This is useful for:
Virtual users created this way are marked as virtual accounts and work across Issues, Feature Requests, and Support Tickets.
Validation Rules:
email: format must match RFC 5322 email format. Invalid emails will fall back to anonymous access.discord_id: format must be numeric (digits only). Invalid discord_ids will fall back to anonymous access.Personal Access Tokens provide enhanced security and can be created and managed in your account settings. They are ideal for API integrations, automated scripts, and CI/CD pipelines. Tokens can have different permissions, including:
| Name | Type | Description |
|---|---|---|
| project_id required | string | |
| issue_id required | string |
| Name | Type | Description |
|---|---|---|
| BetaHub-Project-ID required | string | BetaHub project ID, the same as the project_id |
curl \ -H "Authorization: Bearer YOUR_API_TOKEN" \ -H "BetaHub-Project-ID: 123" \ "https://app.betahub.io/projects/123/issues/g-123/video_clips"
require "net/http" uri = URI("https://app.betahub.io/projects/123/issues/g-123/video_clips") http = Net::HTTP.new(uri.host, uri.port) http.use_ssl = true request = Net::HTTP::Get.new(uri) request["Authorization"] = "Bearer YOUR_API_TOKEN" request["BetaHub-Project-ID"] = "123" response = http.request(request) puts response.body
import requests response = requests.get( "https://app.betahub.io/projects/123/issues/g-123/video_clips", headers={"Authorization": "Bearer YOUR_API_TOKEN", "BetaHub-Project-ID": "123"} ) print(response.json())
const response = await fetch("https://app.betahub.io/projects/123/issues/g-123/video_clips", { headers: { "Authorization": "Bearer YOUR_API_TOKEN", "BetaHub-Project-ID": "123" } }); const data = await response.json();
HttpClient client = HttpClient.newHttpClient(); HttpRequest request = HttpRequest.newBuilder() .uri(URI.create("https://app.betahub.io/projects/123/issues/g-123/video_clips")) .header("Authorization", "Bearer YOUR_API_TOKEN") .header("BetaHub-Project-ID", "123") .GET() .build(); HttpResponse<String> response = client.send( request, HttpResponse.BodyHandlers.ofString()); System.out.println(response.body());
[
{
"id": 0,
"type": "video_clip",
"processing": true,
"processed": true,
"failed": true,
"size_bytes": 0,
"media_size_bytes": 0,
"content_type": "string",
"url": "https://example.com",
"filename": "string",
"created_at": "2026-03-12T10:30:00Z",
"updated_at": "2026-03-12T10:30:00Z",
"user": {
"id": 0,
"name": "string"
}
}
]
{
"error": "string",
"status": "string"
}
Authorization header for API access. Supports multiple authentication methods:
FormUser anonymous - for public operationsFormUser tkn-{token} - for authenticated operations with legacy tokensFormUser tkn-{token},email:{email} - creates/links virtual user by emailFormUser tkn-{token},discord_id:{discord_id} - creates/links virtual user by Discord IDFormUser tkn-{token},{jwt_token} - user identification with JWT token (legacy)Bearer YOUR_TOKEN_HERE - recommended for API integrationsWhen using email: or discord_id: formats with FormUser tokens, the system automatically creates or reuses virtual users. Virtual users are accounts created on-the-fly for form submissions without requiring full user registration. This is useful for:
Virtual users created this way are marked as virtual accounts and work across Issues, Feature Requests, and Support Tickets.
Validation Rules:
email: format must match RFC 5322 email format. Invalid emails will fall back to anonymous access.discord_id: format must be numeric (digits only). Invalid discord_ids will fall back to anonymous access.Personal Access Tokens provide enhanced security and can be created and managed in your account settings. They are ideal for API integrations, automated scripts, and CI/CD pipelines. Tokens can have different permissions, including:
| Name | Type | Description |
|---|---|---|
| project_id required | string | |
| issue_id required | string |
| Name | Type | Description |
|---|---|---|
| BetaHub-Project-ID required | string | BetaHub project ID, the same as the project_id |
curl \ -X POST \ -H "Authorization: Bearer YOUR_API_TOKEN" \ -H "BetaHub-Project-ID: 123" \ -F "video_clip[video]=@file.bin" \ -F "video_clip[name]=string" \ "https://app.betahub.io/projects/123/issues/g-123/video_clips"
require "net/http" require "json" uri = URI("https://app.betahub.io/projects/123/issues/g-123/video_clips") http = Net::HTTP.new(uri.host, uri.port) http.use_ssl = true request = Net::HTTP::Post.new(uri) request["Authorization"] = "Bearer YOUR_API_TOKEN" request["BetaHub-Project-ID"] = "123" response = http.request(request) puts response.body
import requests response = requests.post( "https://app.betahub.io/projects/123/issues/g-123/video_clips", headers={"Authorization": "Bearer YOUR_API_TOKEN", "BetaHub-Project-ID": "123"} ) print(response.json())
const response = await fetch("https://app.betahub.io/projects/123/issues/g-123/video_clips", { method: "POST", headers: { "Authorization": "Bearer YOUR_API_TOKEN", "BetaHub-Project-ID": "123" } }); const data = await response.json();
HttpClient client = HttpClient.newHttpClient(); HttpRequest request = HttpRequest.newBuilder() .uri(URI.create("https://app.betahub.io/projects/123/issues/g-123/video_clips")) .header("Authorization", "Bearer YOUR_API_TOKEN") .header("BetaHub-Project-ID", "123") .header("Content-Type", "application/json") .POST(HttpRequest.BodyPublishers.ofString("{\"video_clip[video]\":\"string\",\"video_clip[name]\":\"string\"}")) .build(); HttpResponse<String> response = client.send( request, HttpResponse.BodyHandlers.ofString()); System.out.println(response.body());
{
"video_clip[video]": "string",
"video_clip[name]": "string"
}
{
"video_clip[video]": "(binary data representing a video file)"
}
| Name | Type | Description |
|---|---|---|
| project_id required | string | |
| issue_id required | string |
curl \ -X POST \ -H "Authorization: Bearer YOUR_API_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "filename": "gameplay.mp4", "byte_size": 52428800, "checksum": "1B2M2Y8AsgTpgAmY7PhCfg==", "content_type": "video/mp4", "name": "Boss Fight Gameplay" }' \ "https://app.betahub.io/projects/123/issues/g-123/video_clips/presigned_upload"
require "net/http" require "json" uri = URI("https://app.betahub.io/projects/123/issues/g-123/video_clips/presigned_upload") http = Net::HTTP.new(uri.host, uri.port) http.use_ssl = true request = Net::HTTP::Post.new(uri) request["Authorization"] = "Bearer YOUR_API_TOKEN" request["Content-Type"] = "application/json" request.body = { "filename": "gameplay.mp4", "byte_size": 52428800, "checksum": "1B2M2Y8AsgTpgAmY7PhCfg==", "content_type": "video/mp4", "name": "Boss Fight Gameplay" } response = http.request(request) puts response.body
import requests response = requests.post( "https://app.betahub.io/projects/123/issues/g-123/video_clips/presigned_upload", headers={"Authorization": "Bearer YOUR_API_TOKEN"}, json={ "filename": "gameplay.mp4", "byte_size": 52428800, "checksum": "1B2M2Y8AsgTpgAmY7PhCfg==", "content_type": "video/mp4", "name": "Boss Fight Gameplay" } ) print(response.json())
const response = await fetch("https://app.betahub.io/projects/123/issues/g-123/video_clips/presigned_upload", { method: "POST", headers: { "Authorization": "Bearer YOUR_API_TOKEN", "Content-Type": "application/json" }, body: JSON.stringify({ "filename": "gameplay.mp4", "byte_size": 52428800, "checksum": "1B2M2Y8AsgTpgAmY7PhCfg==", "content_type": "video/mp4", "name": "Boss Fight Gameplay" }) }); const data = await response.json();
HttpClient client = HttpClient.newHttpClient(); HttpRequest request = HttpRequest.newBuilder() .uri(URI.create("https://app.betahub.io/projects/123/issues/g-123/video_clips/presigned_upload")) .header("Authorization", "Bearer YOUR_API_TOKEN") .header("Content-Type", "application/json") .POST(HttpRequest.BodyPublishers.ofString("{\"filename\":\"gameplay.mp4\",\"byte_size\":52428800,\"checksum\":\"1B2M2Y8AsgTpgAmY7PhCfg==\",\"content_type\":\"video/mp4\",\"name\":\"Boss Fight Gameplay\"}")) .build(); HttpResponse<String> response = client.send( request, HttpResponse.BodyHandlers.ofString()); System.out.println(response.body());
{
"filename": "gameplay.mp4",
"byte_size": 52428800,
"checksum": "1B2M2Y8AsgTpgAmY7PhCfg==",
"content_type": "video/mp4",
"name": "Boss Fight Gameplay"
}
{
"blob_signed_id": "string",
"direct_upload_url": "https://example.com",
"headers": {},
"blob_id": 0
}
{
"errors": [
"string"
],
"message": "string"
}
{
"error": "string",
"status": "string"
}
| Name | Type | Description |
|---|---|---|
| project_id required | string | |
| issue_id required | string |
curl \ -X POST \ -H "Authorization: Bearer YOUR_API_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "blob_signed_id": "string", "name": "Boss Fight Gameplay" }' \ "https://app.betahub.io/projects/123/issues/g-123/video_clips/confirm_upload"
require "net/http" require "json" uri = URI("https://app.betahub.io/projects/123/issues/g-123/video_clips/confirm_upload") http = Net::HTTP.new(uri.host, uri.port) http.use_ssl = true request = Net::HTTP::Post.new(uri) request["Authorization"] = "Bearer YOUR_API_TOKEN" request["Content-Type"] = "application/json" request.body = { "blob_signed_id": "string", "name": "Boss Fight Gameplay" } response = http.request(request) puts response.body
import requests response = requests.post( "https://app.betahub.io/projects/123/issues/g-123/video_clips/confirm_upload", headers={"Authorization": "Bearer YOUR_API_TOKEN"}, json={ "blob_signed_id": "string", "name": "Boss Fight Gameplay" } ) print(response.json())
const response = await fetch("https://app.betahub.io/projects/123/issues/g-123/video_clips/confirm_upload", { method: "POST", headers: { "Authorization": "Bearer YOUR_API_TOKEN", "Content-Type": "application/json" }, body: JSON.stringify({ "blob_signed_id": "string", "name": "Boss Fight Gameplay" }) }); const data = await response.json();
HttpClient client = HttpClient.newHttpClient(); HttpRequest request = HttpRequest.newBuilder() .uri(URI.create("https://app.betahub.io/projects/123/issues/g-123/video_clips/confirm_upload")) .header("Authorization", "Bearer YOUR_API_TOKEN") .header("Content-Type", "application/json") .POST(HttpRequest.BodyPublishers.ofString("{\"blob_signed_id\":\"string\",\"name\":\"Boss Fight Gameplay\"}")) .build(); HttpResponse<String> response = client.send( request, HttpResponse.BodyHandlers.ofString()); System.out.println(response.body());
{
"blob_signed_id": "string",
"name": "Boss Fight Gameplay"
}
{
"id": "string",
"issue_id": "string",
"created_at": "2026-03-12T10:30:00Z",
"updated_at": "2026-03-12T10:30:00Z",
"processing": true,
"processed": true,
"failed": true,
"video_url": "https://example.com"
}
{
"errors": [
"string"
],
"message": "string"
}
{
"error": "string",
"status": "string"
}
Authorization header for API access. Supports multiple authentication methods:
FormUser anonymous - for public operationsFormUser tkn-{token} - for authenticated operations with legacy tokensFormUser tkn-{token},email:{email} - creates/links virtual user by emailFormUser tkn-{token},discord_id:{discord_id} - creates/links virtual user by Discord IDFormUser tkn-{token},{jwt_token} - user identification with JWT token (legacy)Bearer YOUR_TOKEN_HERE - recommended for API integrationsWhen using email: or discord_id: formats with FormUser tokens, the system automatically creates or reuses virtual users. Virtual users are accounts created on-the-fly for form submissions without requiring full user registration. This is useful for:
Virtual users created this way are marked as virtual accounts and work across Issues, Feature Requests, and Support Tickets.
Validation Rules:
email: format must match RFC 5322 email format. Invalid emails will fall back to anonymous access.discord_id: format must be numeric (digits only). Invalid discord_ids will fall back to anonymous access.Personal Access Tokens provide enhanced security and can be created and managed in your account settings. They are ideal for API integrations, automated scripts, and CI/CD pipelines. Tokens can have different permissions, including:
| Name | Type | Description |
|---|---|---|
| project_id required | string |
| Name | Type | Description |
|---|---|---|
| sort optional | string |
Sort order for feature requests. “top” sorts by votes descending, “new” by creation date, “team_picks” shows under_review/planned/started items, “completed” shows completed items, “all” shows all publicly visible items.
top
new
team_picks
completed
all
Default:
top |
| page optional | integer | Page number for pagination (default: 1) |
| Name | Type | Description |
|---|---|---|
| BetaHub-Project-ID required | string | BetaHub project ID, the same as the project_id |
curl \ -H "Authorization: Bearer YOUR_API_TOKEN" \ -H "BetaHub-Project-ID: 123" \ "https://app.betahub.io/projects/123/feature_requests.json?sort=top&page=123"
require "net/http" uri = URI("https://app.betahub.io/projects/123/feature_requests.json?sort=top&page=123") http = Net::HTTP.new(uri.host, uri.port) http.use_ssl = true request = Net::HTTP::Get.new(uri) request["Authorization"] = "Bearer YOUR_API_TOKEN" request["BetaHub-Project-ID"] = "123" response = http.request(request) puts response.body
import requests response = requests.get( "https://app.betahub.io/projects/123/feature_requests.json?sort=top&page=123", headers={"Authorization": "Bearer YOUR_API_TOKEN", "BetaHub-Project-ID": "123"} ) print(response.json())
const response = await fetch("https://app.betahub.io/projects/123/feature_requests.json?sort=top&page=123", { headers: { "Authorization": "Bearer YOUR_API_TOKEN", "BetaHub-Project-ID": "123" } }); const data = await response.json();
HttpClient client = HttpClient.newHttpClient(); HttpRequest request = HttpRequest.newBuilder() .uri(URI.create("https://app.betahub.io/projects/123/feature_requests.json?sort=top&page=123")) .header("Authorization", "Bearer YOUR_API_TOKEN") .header("BetaHub-Project-ID", "123") .GET() .build(); HttpResponse<String> response = client.send( request, HttpResponse.BodyHandlers.ofString()); System.out.println(response.body());
{
"feature_requests": [
{
"id": "string",
"title": "string",
"description": "string",
"status": "open",
"created_at": "2026-03-12T10:30:00Z",
"updated_at": "2026-03-12T10:30:00Z",
"user": {
"id": "string",
"name": "string"
},
"votes": 0,
"voted": true,
"url": "string"
}
],
"pagination": {
"current_page": 0,
"total_pages": 0,
"total_count": 0,
"per_page": 0
},
"sort": "string",
"project_id": 0
}
{
"error": "string",
"status": "string"
}
Authorization header for API access. Supports multiple authentication methods:
FormUser anonymous - for public operationsFormUser tkn-{token} - for authenticated operations with legacy tokensFormUser tkn-{token},email:{email} - creates/links virtual user by emailFormUser tkn-{token},discord_id:{discord_id} - creates/links virtual user by Discord IDFormUser tkn-{token},{jwt_token} - user identification with JWT token (legacy)Bearer YOUR_TOKEN_HERE - recommended for API integrationsWhen using email: or discord_id: formats with FormUser tokens, the system automatically creates or reuses virtual users. Virtual users are accounts created on-the-fly for form submissions without requiring full user registration. This is useful for:
Virtual users created this way are marked as virtual accounts and work across Issues, Feature Requests, and Support Tickets.
Validation Rules:
email: format must match RFC 5322 email format. Invalid emails will fall back to anonymous access.discord_id: format must be numeric (digits only). Invalid discord_ids will fall back to anonymous access.Personal Access Tokens provide enhanced security and can be created and managed in your account settings. They are ideal for API integrations, automated scripts, and CI/CD pipelines. Tokens can have different permissions, including:
| Name | Type | Description |
|---|---|---|
| project_id required | string |
| Name | Type | Description |
|---|---|---|
| BetaHub-Project-ID required | string | BetaHub project ID, the same as the project_id |
FIELD_IDENT with the field’s identifier (e.g., feature_request[custom][category], feature_request[custom][priority_level]). See the issue creation endpoint documentation for details on field types, validation, and JSON format. Use the project’s Custom Fields settings to find available identifiers.
curl \ -X POST \ -H "Authorization: Bearer YOUR_API_TOKEN" \ -H "BetaHub-Project-ID: 123" \ -d "feature_request[description]=Example description" \ -d "feature_request[title]=Example title" \ -d "feature_request[custom][FIELD_IDENT]=string" \ -d "draft=true" \ -d "user[discord_id]=string" \ -d "user[discord_username]=string" \ "https://app.betahub.io/projects/123/feature_requests.json"
require "net/http" require "json" uri = URI("https://app.betahub.io/projects/123/feature_requests.json") http = Net::HTTP.new(uri.host, uri.port) http.use_ssl = true request = Net::HTTP::Post.new(uri) request["Authorization"] = "Bearer YOUR_API_TOKEN" request["BetaHub-Project-ID"] = "123" request.set_form_data({ "feature_request[description]" => "Example description", "feature_request[title]" => "Example title", "feature_request[custom][FIELD_IDENT]" => "string", "draft" => "true", "user[discord_id]" => "string", "user[discord_username]" => "string" }) response = http.request(request) puts response.body
import requests response = requests.post( "https://app.betahub.io/projects/123/feature_requests.json", headers={"Authorization": "Bearer YOUR_API_TOKEN", "BetaHub-Project-ID": "123"}, data={"feature_request[description]": "Example description", "feature_request[title]": "Example title", "feature_request[custom][FIELD_IDENT]": "string", "draft": "true", "user[discord_id]": "string", "user[discord_username]": "string"} ) print(response.json())
const response = await fetch("https://app.betahub.io/projects/123/feature_requests.json", { method: "POST", headers: { "Authorization": "Bearer YOUR_API_TOKEN", "BetaHub-Project-ID": "123" } }); const data = await response.json();
HttpClient client = HttpClient.newHttpClient(); HttpRequest request = HttpRequest.newBuilder() .uri(URI.create("https://app.betahub.io/projects/123/feature_requests.json")) .header("Authorization", "Bearer YOUR_API_TOKEN") .header("BetaHub-Project-ID", "123") .header("Content-Type", "application/json") .POST(HttpRequest.BodyPublishers.ofString("{\"feature_request[description]\":\"string\",\"feature_request[title]\":\"string\",\"feature_request[custom][FIELD_IDENT]\":\"string\",\"draft\":true,\"user[discord_id]\":\"string\",\"user[discord_username]\":\"string\",\"user[discord_discriminator]\":\"string\"}")) .build(); HttpResponse<String> response = client.send( request, HttpResponse.BodyHandlers.ofString()); System.out.println(response.body());
{
"feature_request[description]": "string",
"feature_request[title]": "string",
"feature_request[custom][FIELD_IDENT]": "string",
"draft": true,
"user[discord_id]": "string",
"user[discord_username]": "string",
"user[discord_discriminator]": "string"
}
{
"feature_request[description]": "Add a dark mode to the app",
"user[discord_id]": "123456789",
"user[discord_username]": "username",
"user[discord_discriminator]": "1234"
}
{
"error": "string",
"status": "string"
}
Authorization header for API access. Supports multiple authentication methods:
FormUser anonymous - for public operationsFormUser tkn-{token} - for authenticated operations with legacy tokensFormUser tkn-{token},email:{email} - creates/links virtual user by emailFormUser tkn-{token},discord_id:{discord_id} - creates/links virtual user by Discord IDFormUser tkn-{token},{jwt_token} - user identification with JWT token (legacy)Bearer YOUR_TOKEN_HERE - recommended for API integrationsWhen using email: or discord_id: formats with FormUser tokens, the system automatically creates or reuses virtual users. Virtual users are accounts created on-the-fly for form submissions without requiring full user registration. This is useful for:
Virtual users created this way are marked as virtual accounts and work across Issues, Feature Requests, and Support Tickets.
Validation Rules:
email: format must match RFC 5322 email format. Invalid emails will fall back to anonymous access.discord_id: format must be numeric (digits only). Invalid discord_ids will fall back to anonymous access.Personal Access Tokens provide enhanced security and can be created and managed in your account settings. They are ideal for API integrations, automated scripts, and CI/CD pipelines. Tokens can have different permissions, including:
| Name | Type | Description |
|---|---|---|
| project_id required | string |
| Name | Type | Description |
|---|---|---|
| query required | string | The search query string to match against feature request titles and descriptions |
| skip_ids optional | string | Comma-separated list of feature request IDs to exclude from results |
| partial optional | string |
When set to ‘true’, returns limited results optimized for autocomplete (max 4 results)
true
false
|
| scoped_id optional | string | Instead of searching, find a specific feature request by its scoped ID (e.g., “123” or “fr-456”) |
| Name | Type | Description |
|---|---|---|
| BetaHub-Project-ID required | string | BetaHub project ID, the same as the project_id |
curl \ -H "Authorization: Bearer YOUR_API_TOKEN" \ -H "BetaHub-Project-ID: 123" \ "https://app.betahub.io/projects/123/feature_requests/search.json?query=example&skip_ids=123&partial=true&scoped_id=123"
require "net/http" uri = URI("https://app.betahub.io/projects/123/feature_requests/search.json?query=example&skip_ids=123&partial=true&scoped_id=123") http = Net::HTTP.new(uri.host, uri.port) http.use_ssl = true request = Net::HTTP::Get.new(uri) request["Authorization"] = "Bearer YOUR_API_TOKEN" request["BetaHub-Project-ID"] = "123" response = http.request(request) puts response.body
import requests response = requests.get( "https://app.betahub.io/projects/123/feature_requests/search.json?query=example&skip_ids=123&partial=true&scoped_id=123", headers={"Authorization": "Bearer YOUR_API_TOKEN", "BetaHub-Project-ID": "123"} ) print(response.json())
const response = await fetch("https://app.betahub.io/projects/123/feature_requests/search.json?query=example&skip_ids=123&partial=true&scoped_id=123", { headers: { "Authorization": "Bearer YOUR_API_TOKEN", "BetaHub-Project-ID": "123" } }); const data = await response.json();
HttpClient client = HttpClient.newHttpClient(); HttpRequest request = HttpRequest.newBuilder() .uri(URI.create("https://app.betahub.io/projects/123/feature_requests/search.json?query=example&skip_ids=123&partial=true&scoped_id=123")) .header("Authorization", "Bearer YOUR_API_TOKEN") .header("BetaHub-Project-ID", "123") .GET() .build(); HttpResponse<String> response = client.send( request, HttpResponse.BodyHandlers.ofString()); System.out.println(response.body());
{
"feature_requests": [
{
"id": "1234abc",
"title": "Add dark mode support",
"status": "open",
"created_at": "2024-10-03T12:34:56Z"
}
],
"pagination": {
"current_page": 1,
"per_page": 25,
"total_pages": 2,
"total_count": 42
},
"sort": "top",
"project_id": 123,
"votes": 42,
"voted": false,
"url": "https://app.betahub.io/projects/1/feature_requests/1234abc"
}
{
"error": "string",
"status": "string"
}
{
"error": "string",
"status": "string"
}
Authorization header for API access. Supports multiple authentication methods:
FormUser anonymous - for public operationsFormUser tkn-{token} - for authenticated operations with legacy tokensFormUser tkn-{token},email:{email} - creates/links virtual user by emailFormUser tkn-{token},discord_id:{discord_id} - creates/links virtual user by Discord IDFormUser tkn-{token},{jwt_token} - user identification with JWT token (legacy)Bearer YOUR_TOKEN_HERE - recommended for API integrationsWhen using email: or discord_id: formats with FormUser tokens, the system automatically creates or reuses virtual users. Virtual users are accounts created on-the-fly for form submissions without requiring full user registration. This is useful for:
Virtual users created this way are marked as virtual accounts and work across Issues, Feature Requests, and Support Tickets.
Validation Rules:
email: format must match RFC 5322 email format. Invalid emails will fall back to anonymous access.discord_id: format must be numeric (digits only). Invalid discord_ids will fall back to anonymous access.Personal Access Tokens provide enhanced security and can be created and managed in your account settings. They are ideal for API integrations, automated scripts, and CI/CD pipelines. Tokens can have different permissions, including:
| Name | Type | Description |
|---|---|---|
| project_id required | string | |
| id required | string | The feature request ID or scoped ID |
| Name | Type | Description |
|---|---|---|
| BetaHub-Project-ID required | string | BetaHub project ID, the same as the project_id |
curl \ -H "Authorization: Bearer YOUR_API_TOKEN" \ -H "BetaHub-Project-ID: 123" \ "https://app.betahub.io/projects/123/feature_requests/123.json"
require "net/http" uri = URI("https://app.betahub.io/projects/123/feature_requests/123.json") http = Net::HTTP.new(uri.host, uri.port) http.use_ssl = true request = Net::HTTP::Get.new(uri) request["Authorization"] = "Bearer YOUR_API_TOKEN" request["BetaHub-Project-ID"] = "123" response = http.request(request) puts response.body
import requests response = requests.get( "https://app.betahub.io/projects/123/feature_requests/123.json", headers={"Authorization": "Bearer YOUR_API_TOKEN", "BetaHub-Project-ID": "123"} ) print(response.json())
const response = await fetch("https://app.betahub.io/projects/123/feature_requests/123.json", { headers: { "Authorization": "Bearer YOUR_API_TOKEN", "BetaHub-Project-ID": "123" } }); const data = await response.json();
HttpClient client = HttpClient.newHttpClient(); HttpRequest request = HttpRequest.newBuilder() .uri(URI.create("https://app.betahub.io/projects/123/feature_requests/123.json")) .header("Authorization", "Bearer YOUR_API_TOKEN") .header("BetaHub-Project-ID", "123") .GET() .build(); HttpResponse<String> response = client.send( request, HttpResponse.BodyHandlers.ofString()); System.out.println(response.body());
{
"id": "string",
"title": "string",
"description": "string",
"status": "open",
"created_at": "2026-03-12T10:30:00Z",
"updated_at": "2026-03-12T10:30:00Z",
"user": {
"id": "string",
"name": "string"
},
"votes": 0,
"voted": true,
"url": "string"
}
{
"error": "string",
"status": "string"
}
{
"error": "string",
"status": "string"
}
Authorization header for API access. Supports multiple authentication methods:
FormUser anonymous - for public operationsFormUser tkn-{token} - for authenticated operations with legacy tokensFormUser tkn-{token},email:{email} - creates/links virtual user by emailFormUser tkn-{token},discord_id:{discord_id} - creates/links virtual user by Discord IDFormUser tkn-{token},{jwt_token} - user identification with JWT token (legacy)Bearer YOUR_TOKEN_HERE - recommended for API integrationsWhen using email: or discord_id: formats with FormUser tokens, the system automatically creates or reuses virtual users. Virtual users are accounts created on-the-fly for form submissions without requiring full user registration. This is useful for:
Virtual users created this way are marked as virtual accounts and work across Issues, Feature Requests, and Support Tickets.
Validation Rules:
email: format must match RFC 5322 email format. Invalid emails will fall back to anonymous access.discord_id: format must be numeric (digits only). Invalid discord_ids will fall back to anonymous access.Personal Access Tokens provide enhanced security and can be created and managed in your account settings. They are ideal for API integrations, automated scripts, and CI/CD pipelines. Tokens can have different permissions, including:
| Name | Type | Description |
|---|---|---|
| project_id required | string | |
| id required | string | The feature request ID or scoped ID |
| Name | Type | Description |
|---|---|---|
| BetaHub-Project-ID required | string | BetaHub project ID, the same as the project_id |
curl \ -X POST \ -H "Authorization: Bearer YOUR_API_TOKEN" \ -H "BetaHub-Project-ID: 123" \ -H "Content-Type: application/json" \ -d '{ "email": "user@example.com", "discord_id": "user@example.com" }' \ "https://app.betahub.io/projects/123/feature_requests/123/set_contact_info"
require "net/http" require "json" uri = URI("https://app.betahub.io/projects/123/feature_requests/123/set_contact_info") http = Net::HTTP.new(uri.host, uri.port) http.use_ssl = true request = Net::HTTP::Post.new(uri) request["Authorization"] = "Bearer YOUR_API_TOKEN" request["BetaHub-Project-ID"] = "123" request["Content-Type"] = "application/json" request.body = { "email": "user@example.com", "discord_id": "user@example.com" } response = http.request(request) puts response.body
import requests response = requests.post( "https://app.betahub.io/projects/123/feature_requests/123/set_contact_info", headers={"Authorization": "Bearer YOUR_API_TOKEN", "BetaHub-Project-ID": "123"}, json={ "email": "user@example.com", "discord_id": "user@example.com" } ) print(response.json())
const response = await fetch("https://app.betahub.io/projects/123/feature_requests/123/set_contact_info", { method: "POST", headers: { "Authorization": "Bearer YOUR_API_TOKEN", "BetaHub-Project-ID": "123", "Content-Type": "application/json" }, body: JSON.stringify({ "email": "user@example.com", "discord_id": "user@example.com" }) }); const data = await response.json();
HttpClient client = HttpClient.newHttpClient(); HttpRequest request = HttpRequest.newBuilder() .uri(URI.create("https://app.betahub.io/projects/123/feature_requests/123/set_contact_info")) .header("Authorization", "Bearer YOUR_API_TOKEN") .header("BetaHub-Project-ID", "123") .header("Content-Type", "application/json") .POST(HttpRequest.BodyPublishers.ofString("{\"email\":\"user@example.com\",\"discord_id\":\"user@example.com\"}")) .build(); HttpResponse<String> response = client.send( request, HttpResponse.BodyHandlers.ofString()); System.out.println(response.body());
{
"email": "user@example.com",
"discord_id": "user@example.com"
}
{
"success": true,
"message": "Contact information assigned successfully",
"feature_request_id": "1234",
"user": {
"id": 56,
"email": "user@example.com",
"discord_id": null,
"virtual": true
}
}
{
"error": "string",
"status": "string"
}
{
"error": "string",
"status": "string"
}
{
"error": "string",
"status": "string"
}
Authorization header for API access. Supports multiple authentication methods:
FormUser anonymous - for public operationsFormUser tkn-{token} - for authenticated operations with legacy tokensFormUser tkn-{token},email:{email} - creates/links virtual user by emailFormUser tkn-{token},discord_id:{discord_id} - creates/links virtual user by Discord IDFormUser tkn-{token},{jwt_token} - user identification with JWT token (legacy)Bearer YOUR_TOKEN_HERE - recommended for API integrationsWhen using email: or discord_id: formats with FormUser tokens, the system automatically creates or reuses virtual users. Virtual users are accounts created on-the-fly for form submissions without requiring full user registration. This is useful for:
Virtual users created this way are marked as virtual accounts and work across Issues, Feature Requests, and Support Tickets.
Validation Rules:
email: format must match RFC 5322 email format. Invalid emails will fall back to anonymous access.discord_id: format must be numeric (digits only). Invalid discord_ids will fall back to anonymous access.Personal Access Tokens provide enhanced security and can be created and managed in your account settings. They are ideal for API integrations, automated scripts, and CI/CD pipelines. Tokens can have different permissions, including:
| Name | Type | Description |
|---|---|---|
| project_id required | string | |
| id required | string | The feature request ID or scoped ID |
| Name | Type | Description |
|---|---|---|
| BetaHub-Project-ID required | string | BetaHub project ID, the same as the project_id |
curl \ -X POST \ -H "Authorization: Bearer YOUR_API_TOKEN" \ -H "BetaHub-Project-ID: 123" \ "https://app.betahub.io/projects/123/feature_requests/123/publish"
require "net/http" uri = URI("https://app.betahub.io/projects/123/feature_requests/123/publish") http = Net::HTTP.new(uri.host, uri.port) http.use_ssl = true request = Net::HTTP::Post.new(uri) request["Authorization"] = "Bearer YOUR_API_TOKEN" request["BetaHub-Project-ID"] = "123" response = http.request(request) puts response.body
import requests response = requests.post( "https://app.betahub.io/projects/123/feature_requests/123/publish", headers={"Authorization": "Bearer YOUR_API_TOKEN", "BetaHub-Project-ID": "123"} ) print(response.json())
const response = await fetch("https://app.betahub.io/projects/123/feature_requests/123/publish", { method: "POST", headers: { "Authorization": "Bearer YOUR_API_TOKEN", "BetaHub-Project-ID": "123" } }); const data = await response.json();
HttpClient client = HttpClient.newHttpClient(); HttpRequest request = HttpRequest.newBuilder() .uri(URI.create("https://app.betahub.io/projects/123/feature_requests/123/publish")) .header("Authorization", "Bearer YOUR_API_TOKEN") .header("BetaHub-Project-ID", "123") .method("POST", HttpRequest.BodyPublishers.noBody()) .build(); HttpResponse<String> response = client.send( request, HttpResponse.BodyHandlers.ofString()); System.out.println(response.body());
{
"success": true
}
{
"error": "string",
"status": "string"
}
{
"error": "string",
"status": "string"
}
Authorization header for API access. Supports multiple authentication methods:
FormUser anonymous - for public operationsFormUser tkn-{token} - for authenticated operations with legacy tokensFormUser tkn-{token},email:{email} - creates/links virtual user by emailFormUser tkn-{token},discord_id:{discord_id} - creates/links virtual user by Discord IDFormUser tkn-{token},{jwt_token} - user identification with JWT token (legacy)Bearer YOUR_TOKEN_HERE - recommended for API integrationsWhen using email: or discord_id: formats with FormUser tokens, the system automatically creates or reuses virtual users. Virtual users are accounts created on-the-fly for form submissions without requiring full user registration. This is useful for:
Virtual users created this way are marked as virtual accounts and work across Issues, Feature Requests, and Support Tickets.
Validation Rules:
email: format must match RFC 5322 email format. Invalid emails will fall back to anonymous access.discord_id: format must be numeric (digits only). Invalid discord_ids will fall back to anonymous access.Personal Access Tokens provide enhanced security and can be created and managed in your account settings. They are ideal for API integrations, automated scripts, and CI/CD pipelines. Tokens can have different permissions, including:
| Name | Type | Description |
|---|---|---|
| project_id required | string |
| Name | Type | Description |
|---|---|---|
| query required | string | The search query string to match against ticket titles and descriptions |
| Name | Type | Description |
|---|---|---|
| BetaHub-Project-ID required | string | BetaHub project ID, the same as the project_id |
curl \ -H "Authorization: Bearer YOUR_API_TOKEN" \ -H "BetaHub-Project-ID: 123" \ "https://app.betahub.io/projects/123/tickets/search.json?query=example"
require "net/http" uri = URI("https://app.betahub.io/projects/123/tickets/search.json?query=example") http = Net::HTTP.new(uri.host, uri.port) http.use_ssl = true request = Net::HTTP::Get.new(uri) request["Authorization"] = "Bearer YOUR_API_TOKEN" request["BetaHub-Project-ID"] = "123" response = http.request(request) puts response.body
import requests response = requests.get( "https://app.betahub.io/projects/123/tickets/search.json?query=example", headers={"Authorization": "Bearer YOUR_API_TOKEN", "BetaHub-Project-ID": "123"} ) print(response.json())
const response = await fetch("https://app.betahub.io/projects/123/tickets/search.json?query=example", { headers: { "Authorization": "Bearer YOUR_API_TOKEN", "BetaHub-Project-ID": "123" } }); const data = await response.json();
HttpClient client = HttpClient.newHttpClient(); HttpRequest request = HttpRequest.newBuilder() .uri(URI.create("https://app.betahub.io/projects/123/tickets/search.json?query=example")) .header("Authorization", "Bearer YOUR_API_TOKEN") .header("BetaHub-Project-ID", "123") .GET() .build(); HttpResponse<String> response = client.send( request, HttpResponse.BodyHandlers.ofString()); System.out.println(response.body());
[
{
"id": "123",
"title": "Cannot access user settings"
},
{
"id": "456",
"title": "Password reset not working"
}
]
{
"error": "string",
"status": "string"
}
Creates a new support ticket for a project. Support tickets are used for customer support, help requests, and technical assistance.
FormUser tkn-{token},email:{email} header OR provide ticket[reporter_email] in form data to create/link virtual user by email - FormUser with Discord ID: Use FormUser tkn-{token},discord_id:{discord_id} header to create/link virtual user by Discord ID - Discord Bot: Can create tickets on behalf of Discord users by providing discord_id, discord_username, and discord_discriminator in form data - Authenticated Users: Tickets are created with current_user as reporter - Anonymous Users: Must provide reporter_email in form data or email/discord_id in auth header. Anonymous ticket creation without contact info is not allowed.
Authorization header for API access. Supports multiple authentication methods:
FormUser anonymous - for public operationsFormUser tkn-{token} - for authenticated operations with legacy tokensFormUser tkn-{token},email:{email} - creates/links virtual user by emailFormUser tkn-{token},discord_id:{discord_id} - creates/links virtual user by Discord IDFormUser tkn-{token},{jwt_token} - user identification with JWT token (legacy)Bearer YOUR_TOKEN_HERE - recommended for API integrationsWhen using email: or discord_id: formats with FormUser tokens, the system automatically creates or reuses virtual users. Virtual users are accounts created on-the-fly for form submissions without requiring full user registration. This is useful for:
Virtual users created this way are marked as virtual accounts and work across Issues, Feature Requests, and Support Tickets.
Validation Rules:
email: format must match RFC 5322 email format. Invalid emails will fall back to anonymous access.discord_id: format must be numeric (digits only). Invalid discord_ids will fall back to anonymous access.Personal Access Tokens provide enhanced security and can be created and managed in your account settings. They are ideal for API integrations, automated scripts, and CI/CD pipelines. Tokens can have different permissions, including:
| Name | Type | Description |
|---|---|---|
| project_id required | string |
| Name | Type | Description |
|---|---|---|
| BetaHub-Project-ID required | string | BetaHub project ID, the same as the project_id |
FIELD_IDENT with the field’s identifier (e.g., ticket[custom][platform], ticket[custom][priority_level]). See the issue creation endpoint documentation for details on field types, validation, and JSON format. Use the project’s Custom Fields settings to find available identifiers.
curl \ -X POST \ -H "Authorization: Bearer YOUR_API_TOKEN" \ -H "BetaHub-Project-ID: 123" \ -F "ticket[description]=Example description" \ -F "ticket[title]=Example title" \ -F "ticket[priority]=low" \ -F "ticket[attachments][]=string" \ "https://app.betahub.io/projects/123/tickets.json"
require "net/http" require "json" uri = URI("https://app.betahub.io/projects/123/tickets.json") http = Net::HTTP.new(uri.host, uri.port) http.use_ssl = true request = Net::HTTP::Post.new(uri) request["Authorization"] = "Bearer YOUR_API_TOKEN" request["BetaHub-Project-ID"] = "123" response = http.request(request) puts response.body
import requests response = requests.post( "https://app.betahub.io/projects/123/tickets.json", headers={"Authorization": "Bearer YOUR_API_TOKEN", "BetaHub-Project-ID": "123"} ) print(response.json())
const response = await fetch("https://app.betahub.io/projects/123/tickets.json", { method: "POST", headers: { "Authorization": "Bearer YOUR_API_TOKEN", "BetaHub-Project-ID": "123" } }); const data = await response.json();
HttpClient client = HttpClient.newHttpClient(); HttpRequest request = HttpRequest.newBuilder() .uri(URI.create("https://app.betahub.io/projects/123/tickets.json")) .header("Authorization", "Bearer YOUR_API_TOKEN") .header("BetaHub-Project-ID", "123") .header("Content-Type", "application/json") .POST(HttpRequest.BodyPublishers.ofString("{\"ticket[description]\":\"string\",\"ticket[title]\":\"string\",\"ticket[priority]\":\"low\",\"ticket[attachments][]\":[\"string\"],\"ticket[custom][FIELD_IDENT]\":\"string\",\"ticket[reporter_email]\":\"user@example.com\",\"user[discord_id]\":\"string\",\"user[discord_username]\":\"string\",\"user[discord_discriminator]\":\"string\"}")) .build(); HttpResponse<String> response = client.send( request, HttpResponse.BodyHandlers.ofString()); System.out.println(response.body());
{
"ticket[description]": "string",
"ticket[title]": "string",
"ticket[priority]": "low",
"ticket[attachments][]": [
"string"
],
"ticket[custom][FIELD_IDENT]": "string",
"ticket[reporter_email]": "user@example.com",
"user[discord_id]": "string",
"user[discord_username]": "string",
"user[discord_discriminator]": "string"
}
{
"ticket[description]": "I need help resetting my password",
"ticket[priority]": "high"
}
{
"error": "Description can't be blank"
}
{
"error": "Authentication required for creating support tickets"
}
{
"error": "string",
"status": "string"
}
Authorization header for API access. Supports multiple authentication methods:
FormUser anonymous - for public operationsFormUser tkn-{token} - for authenticated operations with legacy tokensFormUser tkn-{token},email:{email} - creates/links virtual user by emailFormUser tkn-{token},discord_id:{discord_id} - creates/links virtual user by Discord IDFormUser tkn-{token},{jwt_token} - user identification with JWT token (legacy)Bearer YOUR_TOKEN_HERE - recommended for API integrationsWhen using email: or discord_id: formats with FormUser tokens, the system automatically creates or reuses virtual users. Virtual users are accounts created on-the-fly for form submissions without requiring full user registration. This is useful for:
Virtual users created this way are marked as virtual accounts and work across Issues, Feature Requests, and Support Tickets.
Validation Rules:
email: format must match RFC 5322 email format. Invalid emails will fall back to anonymous access.discord_id: format must be numeric (digits only). Invalid discord_ids will fall back to anonymous access.Personal Access Tokens provide enhanced security and can be created and managed in your account settings. They are ideal for API integrations, automated scripts, and CI/CD pipelines. Tokens can have different permissions, including:
| Name | Type | Description |
|---|---|---|
| project_id required | string | |
| id required | string | The ticket ID. Can be a numeric ID or scoped ID format. |
| Name | Type | Description |
|---|---|---|
| BetaHub-Project-ID required | string | BetaHub project ID, the same as the project_id |
curl \ -H "Authorization: Bearer YOUR_API_TOKEN" \ -H "BetaHub-Project-ID: 123" \ "https://app.betahub.io/projects/123/tickets/123.json"
require "net/http" uri = URI("https://app.betahub.io/projects/123/tickets/123.json") http = Net::HTTP.new(uri.host, uri.port) http.use_ssl = true request = Net::HTTP::Get.new(uri) request["Authorization"] = "Bearer YOUR_API_TOKEN" request["BetaHub-Project-ID"] = "123" response = http.request(request) puts response.body
import requests response = requests.get( "https://app.betahub.io/projects/123/tickets/123.json", headers={"Authorization": "Bearer YOUR_API_TOKEN", "BetaHub-Project-ID": "123"} ) print(response.json())
const response = await fetch("https://app.betahub.io/projects/123/tickets/123.json", { headers: { "Authorization": "Bearer YOUR_API_TOKEN", "BetaHub-Project-ID": "123" } }); const data = await response.json();
HttpClient client = HttpClient.newHttpClient(); HttpRequest request = HttpRequest.newBuilder() .uri(URI.create("https://app.betahub.io/projects/123/tickets/123.json")) .header("Authorization", "Bearer YOUR_API_TOKEN") .header("BetaHub-Project-ID", "123") .GET() .build(); HttpResponse<String> response = client.send( request, HttpResponse.BodyHandlers.ofString()); System.out.println(response.body());
{
"id": "123",
"title": "Password reset assistance needed",
"description": "I need help resetting my password",
"status": "open",
"priority": "high",
"created_at": "2024-10-06T10:00:00Z",
"updated_at": "2024-10-06T10:30:00Z",
"reporter": {
"id": "456",
"name": "John Doe"
},
"assigned_to": {
"id": "789",
"name": "Support Agent"
},
"url": "https://app.betahub.io/projects/1/tickets/123",
"attachments": [
{
"id": "101",
"filename": "screenshot.png",
"url": "https://cdn.betahub.io/attachments/101/screenshot.png",
"content_type": "image/png",
"file_type": "image",
"size_bytes": 245678,
"user": {
"id": "456",
"name": "John Doe"
}
}
]
}
{
"error": "string",
"status": "string"
}
{
"error": "string",
"status": "string"
}
Updates an existing support ticket with new information. This endpoint supports comprehensive ticket management including:
Authorization header for API access. Supports multiple authentication methods:
FormUser anonymous - for public operationsFormUser tkn-{token} - for authenticated operations with legacy tokensFormUser tkn-{token},email:{email} - creates/links virtual user by emailFormUser tkn-{token},discord_id:{discord_id} - creates/links virtual user by Discord IDFormUser tkn-{token},{jwt_token} - user identification with JWT token (legacy)Bearer YOUR_TOKEN_HERE - recommended for API integrationsWhen using email: or discord_id: formats with FormUser tokens, the system automatically creates or reuses virtual users. Virtual users are accounts created on-the-fly for form submissions without requiring full user registration. This is useful for:
Virtual users created this way are marked as virtual accounts and work across Issues, Feature Requests, and Support Tickets.
Validation Rules:
email: format must match RFC 5322 email format. Invalid emails will fall back to anonymous access.discord_id: format must be numeric (digits only). Invalid discord_ids will fall back to anonymous access.Personal Access Tokens provide enhanced security and can be created and managed in your account settings. They are ideal for API integrations, automated scripts, and CI/CD pipelines. Tokens can have different permissions, including:
| Name | Type | Description |
|---|---|---|
| project_id required | string | |
| id required | string | The ticket ID. Can be a numeric ID or scoped ID format. |
| Name | Type | Description |
|---|---|---|
| BetaHub-Project-ID required | string | BetaHub project ID, the same as the project_id |
curl \ -X PATCH \ -H "Authorization: Bearer YOUR_API_TOKEN" \ -H "BetaHub-Project-ID: 123" \ -F "ticket[title]=Example title" \ -F "ticket[description]=Example description" \ -F "ticket[status]=new" \ -F "ticket[priority]=low" \ "https://app.betahub.io/projects/123/tickets/123.json"
require "net/http" require "json" uri = URI("https://app.betahub.io/projects/123/tickets/123.json") http = Net::HTTP.new(uri.host, uri.port) http.use_ssl = true request = Net::HTTP::Patch.new(uri) request["Authorization"] = "Bearer YOUR_API_TOKEN" request["BetaHub-Project-ID"] = "123" response = http.request(request) puts response.body
import requests response = requests.patch( "https://app.betahub.io/projects/123/tickets/123.json", headers={"Authorization": "Bearer YOUR_API_TOKEN", "BetaHub-Project-ID": "123"} ) print(response.json())
const response = await fetch("https://app.betahub.io/projects/123/tickets/123.json", { method: "PATCH", headers: { "Authorization": "Bearer YOUR_API_TOKEN", "BetaHub-Project-ID": "123" } }); const data = await response.json();
HttpClient client = HttpClient.newHttpClient(); HttpRequest request = HttpRequest.newBuilder() .uri(URI.create("https://app.betahub.io/projects/123/tickets/123.json")) .header("Authorization", "Bearer YOUR_API_TOKEN") .header("BetaHub-Project-ID", "123") .header("Content-Type", "application/json") .PATCH(HttpRequest.BodyPublishers.ofString("{\"ticket[title]\":\"string\",\"ticket[description]\":\"string\",\"ticket[status]\":\"new\",\"ticket[priority]\":\"low\",\"ticket[assigned_to_id]\":\"string\",\"ticket[attachments][]\":[\"string\"],\"ticket[remove_attachment_ids][]\":[\"string\"]}")) .build(); HttpResponse<String> response = client.send( request, HttpResponse.BodyHandlers.ofString()); System.out.println(response.body());
{
"ticket[title]": "string",
"ticket[description]": "string",
"ticket[status]": "new",
"ticket[priority]": "low",
"ticket[assigned_to_id]": "string",
"ticket[attachments][]": [
"string"
],
"ticket[remove_attachment_ids][]": [
"string"
]
}
{
"ticket[status]": "solved",
"ticket[description]": "Issue resolved - password reset email sent"
}
{
"error": "Description can't be blank"
}
{
"error": "string",
"status": "string"
}
{
"error": "string",
"status": "string"
}
show_drafts parameter (developers only) to include draft releases, or show_archived to include archived releases.Authorization header for API access. Supports multiple authentication methods:
FormUser anonymous - for public operationsFormUser tkn-{token} - for authenticated operations with legacy tokensFormUser tkn-{token},email:{email} - creates/links virtual user by emailFormUser tkn-{token},discord_id:{discord_id} - creates/links virtual user by Discord IDFormUser tkn-{token},{jwt_token} - user identification with JWT token (legacy)Bearer YOUR_TOKEN_HERE - recommended for API integrationsWhen using email: or discord_id: formats with FormUser tokens, the system automatically creates or reuses virtual users. Virtual users are accounts created on-the-fly for form submissions without requiring full user registration. This is useful for:
Virtual users created this way are marked as virtual accounts and work across Issues, Feature Requests, and Support Tickets.
Validation Rules:
email: format must match RFC 5322 email format. Invalid emails will fall back to anonymous access.discord_id: format must be numeric (digits only). Invalid discord_ids will fall back to anonymous access.Personal Access Tokens provide enhanced security and can be created and managed in your account settings. They are ideal for API integrations, automated scripts, and CI/CD pipelines. Tokens can have different permissions, including:
| Name | Type | Description |
|---|---|---|
| project_id required | string |
| Name | Type | Description |
|---|---|---|
| sort optional | string |
Sort order by creation date. asc for oldest first (default), desc for newest first.
asc
desc
Default:
asc |
| show_drafts optional | string |
Include draft releases in the response. Only project developers can view drafts. Set to true to show draft releases. This parameter is ignored for non-developers.
true
false
Default:
false |
| show_archived optional | string |
Include archived releases in the response. Set to true to show archived releases.
true
false
Default:
false |
| Name | Type | Description |
|---|---|---|
| BetaHub-Project-ID required | string | BetaHub project ID, the same as the project_id |
curl \ -H "Authorization: Bearer YOUR_API_TOKEN" \ -H "BetaHub-Project-ID: 123" \ "https://app.betahub.io/projects/123/releases.json?sort=asc&show_drafts=false&show_archived=false"
require "net/http" uri = URI("https://app.betahub.io/projects/123/releases.json?sort=asc&show_drafts=false&show_archived=false") http = Net::HTTP.new(uri.host, uri.port) http.use_ssl = true request = Net::HTTP::Get.new(uri) request["Authorization"] = "Bearer YOUR_API_TOKEN" request["BetaHub-Project-ID"] = "123" response = http.request(request) puts response.body
import requests response = requests.get( "https://app.betahub.io/projects/123/releases.json?sort=asc&show_drafts=false&show_archived=false", headers={"Authorization": "Bearer YOUR_API_TOKEN", "BetaHub-Project-ID": "123"} ) print(response.json())
const response = await fetch("https://app.betahub.io/projects/123/releases.json?sort=asc&show_drafts=false&show_archived=false", { headers: { "Authorization": "Bearer YOUR_API_TOKEN", "BetaHub-Project-ID": "123" } }); const data = await response.json();
HttpClient client = HttpClient.newHttpClient(); HttpRequest request = HttpRequest.newBuilder() .uri(URI.create("https://app.betahub.io/projects/123/releases.json?sort=asc&show_drafts=false&show_archived=false")) .header("Authorization", "Bearer YOUR_API_TOKEN") .header("BetaHub-Project-ID", "123") .GET() .build(); HttpResponse<String> response = client.send( request, HttpResponse.BodyHandlers.ofString()); System.out.println(response.body());
[
{
"id": "rel-123abc",
"label": "v1.0.0",
"summary": "Initial release",
"description": "First stable version of our game",
"status": "published",
"active": true,
"release_type": "regular",
"created_at": "2024-10-03T12:34:56Z",
"updated_at": "2024-10-03T12:34:56Z",
"download_links": [
{
"platform": "windows",
"url": "https://example.com/download/game-v1.0.0-windows.zip"
},
{
"platform": "macos",
"url": "https://example.com/download/game-v1.0.0-macos.dmg"
}
],
"attachments_count": 2,
"url": "https://app.betahub.io/projects/1/releases/rel-123abc"
}
]
{
"error": "string",
"status": "string"
}
{
"error": "string",
"status": "string"
}
release[status]=draft to create a draft release that can be edited before publishing.Authorization header for API access. Supports multiple authentication methods:
FormUser anonymous - for public operationsFormUser tkn-{token} - for authenticated operations with legacy tokensFormUser tkn-{token},email:{email} - creates/links virtual user by emailFormUser tkn-{token},discord_id:{discord_id} - creates/links virtual user by Discord IDFormUser tkn-{token},{jwt_token} - user identification with JWT token (legacy)Bearer YOUR_TOKEN_HERE - recommended for API integrationsWhen using email: or discord_id: formats with FormUser tokens, the system automatically creates or reuses virtual users. Virtual users are accounts created on-the-fly for form submissions without requiring full user registration. This is useful for:
Virtual users created this way are marked as virtual accounts and work across Issues, Feature Requests, and Support Tickets.
Validation Rules:
email: format must match RFC 5322 email format. Invalid emails will fall back to anonymous access.discord_id: format must be numeric (digits only). Invalid discord_ids will fall back to anonymous access.Personal Access Tokens provide enhanced security and can be created and managed in your account settings. They are ideal for API integrations, automated scripts, and CI/CD pipelines. Tokens can have different permissions, including:
| Name | Type | Description |
|---|---|---|
| project_id required | string |
| Name | Type | Description |
|---|---|---|
| BetaHub-Project-ID required | string | BetaHub project ID, the same as the project_id |
draft to create a draft release that is only visible to developers and does not trigger notifications. Set to published (default) to publish immediately and notify project members.
curl \ -X POST \ -H "Authorization: Bearer YOUR_API_TOKEN" \ -H "BetaHub-Project-ID: 123" \ -F "release[label]=string" \ -F "release[summary]=string" \ -F "release[description]=Example description" \ -F "release[send_images_separately]=true" \ "https://app.betahub.io/projects/123/releases.json"
require "net/http" require "json" uri = URI("https://app.betahub.io/projects/123/releases.json") http = Net::HTTP.new(uri.host, uri.port) http.use_ssl = true request = Net::HTTP::Post.new(uri) request["Authorization"] = "Bearer YOUR_API_TOKEN" request["BetaHub-Project-ID"] = "123" response = http.request(request) puts response.body
import requests response = requests.post( "https://app.betahub.io/projects/123/releases.json", headers={"Authorization": "Bearer YOUR_API_TOKEN", "BetaHub-Project-ID": "123"} ) print(response.json())
const response = await fetch("https://app.betahub.io/projects/123/releases.json", { method: "POST", headers: { "Authorization": "Bearer YOUR_API_TOKEN", "BetaHub-Project-ID": "123" } }); const data = await response.json();
HttpClient client = HttpClient.newHttpClient(); HttpRequest request = HttpRequest.newBuilder() .uri(URI.create("https://app.betahub.io/projects/123/releases.json")) .header("Authorization", "Bearer YOUR_API_TOKEN") .header("BetaHub-Project-ID", "123") .header("Content-Type", "application/json") .POST(HttpRequest.BodyPublishers.ofString("{\"release[label]\":\"string\",\"release[summary]\":\"string\",\"release[description]\":\"string\",\"release[send_images_separately]\":true,\"release[attachments]\":[\"string\"],\"release[download_links_attributes]\":[{\"platform\":\"string\",\"url\":\"https://example.com\",\"link_enabled\":true}],\"release[status]\":\"draft\"}")) .build(); HttpResponse<String> response = client.send( request, HttpResponse.BodyHandlers.ofString()); System.out.println(response.body());
{
"release[label]": "string",
"release[summary]": "string",
"release[description]": "string",
"release[send_images_separately]": true,
"release[attachments]": [
"string"
],
"release[download_links_attributes]": [
{
"platform": "string",
"url": "https://example.com",
"link_enabled": true
}
],
"release[status]": "draft"
}
{
"release[label]": "v1.1.0",
"release[summary]": "Bug fixes and improvements",
"release[description]": "This release includes several bug fixes and performance improvements.",
"release[download_links_attributes]": [
{
"platform": "windows",
"url": "https://example.com/download/game-v1.1.0-windows.zip",
"link_enabled": true
}
]
}
{
"error": "string",
"status": "string"
}
{
"error": "string",
"status": "string"
}
Authorization header for API access. Supports multiple authentication methods:
FormUser anonymous - for public operationsFormUser tkn-{token} - for authenticated operations with legacy tokensFormUser tkn-{token},email:{email} - creates/links virtual user by emailFormUser tkn-{token},discord_id:{discord_id} - creates/links virtual user by Discord IDFormUser tkn-{token},{jwt_token} - user identification with JWT token (legacy)Bearer YOUR_TOKEN_HERE - recommended for API integrationsWhen using email: or discord_id: formats with FormUser tokens, the system automatically creates or reuses virtual users. Virtual users are accounts created on-the-fly for form submissions without requiring full user registration. This is useful for:
Virtual users created this way are marked as virtual accounts and work across Issues, Feature Requests, and Support Tickets.
Validation Rules:
email: format must match RFC 5322 email format. Invalid emails will fall back to anonymous access.discord_id: format must be numeric (digits only). Invalid discord_ids will fall back to anonymous access.Personal Access Tokens provide enhanced security and can be created and managed in your account settings. They are ideal for API integrations, automated scripts, and CI/CD pipelines. Tokens can have different permissions, including:
| Name | Type | Description |
|---|---|---|
| project_id required | string | |
| release_id required | string |
| Name | Type | Description |
|---|---|---|
| BetaHub-Project-ID required | string | BetaHub project ID, the same as the project_id |
curl \ -H "Authorization: Bearer YOUR_API_TOKEN" \ -H "BetaHub-Project-ID: 123" \ "https://app.betahub.io/projects/123/releases/123.json"
require "net/http" uri = URI("https://app.betahub.io/projects/123/releases/123.json") http = Net::HTTP.new(uri.host, uri.port) http.use_ssl = true request = Net::HTTP::Get.new(uri) request["Authorization"] = "Bearer YOUR_API_TOKEN" request["BetaHub-Project-ID"] = "123" response = http.request(request) puts response.body
import requests response = requests.get( "https://app.betahub.io/projects/123/releases/123.json", headers={"Authorization": "Bearer YOUR_API_TOKEN", "BetaHub-Project-ID": "123"} ) print(response.json())
const response = await fetch("https://app.betahub.io/projects/123/releases/123.json", { headers: { "Authorization": "Bearer YOUR_API_TOKEN", "BetaHub-Project-ID": "123" } }); const data = await response.json();
HttpClient client = HttpClient.newHttpClient(); HttpRequest request = HttpRequest.newBuilder() .uri(URI.create("https://app.betahub.io/projects/123/releases/123.json")) .header("Authorization", "Bearer YOUR_API_TOKEN") .header("BetaHub-Project-ID", "123") .GET() .build(); HttpResponse<String> response = client.send( request, HttpResponse.BodyHandlers.ofString()); System.out.println(response.body());
{
"id": "rel-123abc",
"label": "v1.0.0",
"summary": "Initial release",
"description": "First stable version of our game",
"status": "published",
"active": true,
"release_type": "regular",
"created_at": "2024-10-03T12:34:56Z",
"updated_at": "2024-10-03T12:34:56Z",
"download_links": [
{
"platform": "windows",
"url": "https://example.com/download/game-v1.0.0-windows.zip"
},
{
"platform": "macos",
"url": "https://example.com/download/game-v1.0.0-macos.dmg"
}
],
"attachments_count": 2,
"url": "https://app.betahub.io/projects/1/releases/rel-123abc"
}
{
"error": "string",
"status": "string"
}
{
"error": "string",
"status": "string"
}
Authorization header for API access. Supports multiple authentication methods:
FormUser anonymous - for public operationsFormUser tkn-{token} - for authenticated operations with legacy tokensFormUser tkn-{token},email:{email} - creates/links virtual user by emailFormUser tkn-{token},discord_id:{discord_id} - creates/links virtual user by Discord IDFormUser tkn-{token},{jwt_token} - user identification with JWT token (legacy)Bearer YOUR_TOKEN_HERE - recommended for API integrationsWhen using email: or discord_id: formats with FormUser tokens, the system automatically creates or reuses virtual users. Virtual users are accounts created on-the-fly for form submissions without requiring full user registration. This is useful for:
Virtual users created this way are marked as virtual accounts and work across Issues, Feature Requests, and Support Tickets.
Validation Rules:
email: format must match RFC 5322 email format. Invalid emails will fall back to anonymous access.discord_id: format must be numeric (digits only). Invalid discord_ids will fall back to anonymous access.Personal Access Tokens provide enhanced security and can be created and managed in your account settings. They are ideal for API integrations, automated scripts, and CI/CD pipelines. Tokens can have different permissions, including:
| Name | Type | Description |
|---|---|---|
| project_id required | string | |
| release_id required | string |
| Name | Type | Description |
|---|---|---|
| BetaHub-Project-ID required | string | BetaHub project ID, the same as the project_id |
curl \ -X PUT \ -H "Authorization: Bearer YOUR_API_TOKEN" \ -H "BetaHub-Project-ID: 123" \ -H "Content-Type: application/json" \ -d '{ "release[label]": "string", "release[summary]": "string", "release[description]": "string", "release[send_images_separately]": true, "release[download_links_attributes]": [ { "id": "https://example.com", "platform": "string", "url": "https://example.com", "link_enabled": true } ], "release[remove_attachments]": [ "string" ], "release[attachments]": [ "string" ] }' \ "https://app.betahub.io/projects/123/releases/123.json"
require "net/http" require "json" uri = URI("https://app.betahub.io/projects/123/releases/123.json") http = Net::HTTP.new(uri.host, uri.port) http.use_ssl = true request = Net::HTTP::Put.new(uri) request["Authorization"] = "Bearer YOUR_API_TOKEN" request["BetaHub-Project-ID"] = "123" request["Content-Type"] = "application/json" request.body = { "release[label]": "string", "release[summary]": "string", "release[description]": "string", "release[send_images_separately]": true, "release[download_links_attributes]": [ { "id": "https://example.com", "platform": "string", "url": "https://example.com", "link_enabled": true } ], "release[remove_attachments]": [ "string" ], "release[attachments]": [ "string" ] } response = http.request(request) puts response.body
import requests response = requests.put( "https://app.betahub.io/projects/123/releases/123.json", headers={"Authorization": "Bearer YOUR_API_TOKEN", "BetaHub-Project-ID": "123"}, json={ "release[label]": "string", "release[summary]": "string", "release[description]": "string", "release[send_images_separately]": true, "release[download_links_attributes]": [ { "id": "https://example.com", "platform": "string", "url": "https://example.com", "link_enabled": true } ], "release[remove_attachments]": [ "string" ], "release[attachments]": [ "string" ] } ) print(response.json())
const response = await fetch("https://app.betahub.io/projects/123/releases/123.json", { method: "PUT", headers: { "Authorization": "Bearer YOUR_API_TOKEN", "BetaHub-Project-ID": "123", "Content-Type": "application/json" }, body: JSON.stringify({ "release[label]": "string", "release[summary]": "string", "release[description]": "string", "release[send_images_separately]": true, "release[download_links_attributes]": [ { "id": "https://example.com", "platform": "string", "url": "https://example.com", "link_enabled": true } ], "release[remove_attachments]": [ "string" ], "release[attachments]": [ "string" ] }) }); const data = await response.json();
HttpClient client = HttpClient.newHttpClient(); HttpRequest request = HttpRequest.newBuilder() .uri(URI.create("https://app.betahub.io/projects/123/releases/123.json")) .header("Authorization", "Bearer YOUR_API_TOKEN") .header("BetaHub-Project-ID", "123") .header("Content-Type", "application/json") .PUT(HttpRequest.BodyPublishers.ofString("{\"release[label]\":\"string\",\"release[summary]\":\"string\",\"release[description]\":\"string\",\"release[send_images_separately]\":true,\"release[download_links_attributes]\":[{\"id\":\"https://example.com\",\"platform\":\"string\",\"url\":\"https://example.com\",\"link_enabled\":true}],\"release[remove_attachments]\":[\"string\"],\"release[attachments]\":[\"string\"]}")) .build(); HttpResponse<String> response = client.send( request, HttpResponse.BodyHandlers.ofString()); System.out.println(response.body());
{
"release[label]": "string",
"release[summary]": "string",
"release[description]": "string",
"release[send_images_separately]": true,
"release[download_links_attributes]": [
{
"id": "https://example.com",
"platform": "string",
"url": "https://example.com",
"link_enabled": true
}
],
"release[remove_attachments]": [
"string"
],
"release[attachments]": [
"string"
]
}
{
"release[label]": "v1.0.1",
"release[summary]": "Hotfix release",
"release[description]": "Critical bug fixes for v1.0.0"
}
{
"error": "string",
"status": "string"
}
{
"error": "string",
"status": "string"
}
{
"error": "string",
"status": "string"
}
Authorization header for API access. Supports multiple authentication methods:
FormUser anonymous - for public operationsFormUser tkn-{token} - for authenticated operations with legacy tokensFormUser tkn-{token},email:{email} - creates/links virtual user by emailFormUser tkn-{token},discord_id:{discord_id} - creates/links virtual user by Discord IDFormUser tkn-{token},{jwt_token} - user identification with JWT token (legacy)Bearer YOUR_TOKEN_HERE - recommended for API integrationsWhen using email: or discord_id: formats with FormUser tokens, the system automatically creates or reuses virtual users. Virtual users are accounts created on-the-fly for form submissions without requiring full user registration. This is useful for:
Virtual users created this way are marked as virtual accounts and work across Issues, Feature Requests, and Support Tickets.
Validation Rules:
email: format must match RFC 5322 email format. Invalid emails will fall back to anonymous access.discord_id: format must be numeric (digits only). Invalid discord_ids will fall back to anonymous access.Personal Access Tokens provide enhanced security and can be created and managed in your account settings. They are ideal for API integrations, automated scripts, and CI/CD pipelines. Tokens can have different permissions, including:
| Name | Type | Description |
|---|---|---|
| project_id required | string | |
| release_id required | string |
| Name | Type | Description |
|---|---|---|
| BetaHub-Project-ID required | string | BetaHub project ID, the same as the project_id |
curl \ -X DELETE \ -H "Authorization: Bearer YOUR_API_TOKEN" \ -H "BetaHub-Project-ID: 123" \ "https://app.betahub.io/projects/123/releases/123.json"
require "net/http" uri = URI("https://app.betahub.io/projects/123/releases/123.json") http = Net::HTTP.new(uri.host, uri.port) http.use_ssl = true request = Net::HTTP::Delete.new(uri) request["Authorization"] = "Bearer YOUR_API_TOKEN" request["BetaHub-Project-ID"] = "123" response = http.request(request) puts response.body
import requests response = requests.delete( "https://app.betahub.io/projects/123/releases/123.json", headers={"Authorization": "Bearer YOUR_API_TOKEN", "BetaHub-Project-ID": "123"} ) print(response.json())
const response = await fetch("https://app.betahub.io/projects/123/releases/123.json", { method: "DELETE", headers: { "Authorization": "Bearer YOUR_API_TOKEN", "BetaHub-Project-ID": "123" } }); const data = await response.json();
HttpClient client = HttpClient.newHttpClient(); HttpRequest request = HttpRequest.newBuilder() .uri(URI.create("https://app.betahub.io/projects/123/releases/123.json")) .header("Authorization", "Bearer YOUR_API_TOKEN") .header("BetaHub-Project-ID", "123") .method("DELETE", HttpRequest.BodyPublishers.noBody()) .build(); HttpResponse<String> response = client.send( request, HttpResponse.BodyHandlers.ofString()); System.out.println(response.body());
{
"success": true,
"message": "Release was successfully deleted."
}
{
"error": "Cannot delete the only published release for this project. Archive it instead."
}
{
"error": "string",
"status": "string"
}
{
"error": "string",
"status": "string"
}
Authorization header for API access. Supports multiple authentication methods:
FormUser anonymous - for public operationsFormUser tkn-{token} - for authenticated operations with legacy tokensFormUser tkn-{token},email:{email} - creates/links virtual user by emailFormUser tkn-{token},discord_id:{discord_id} - creates/links virtual user by Discord IDFormUser tkn-{token},{jwt_token} - user identification with JWT token (legacy)Bearer YOUR_TOKEN_HERE - recommended for API integrationsWhen using email: or discord_id: formats with FormUser tokens, the system automatically creates or reuses virtual users. Virtual users are accounts created on-the-fly for form submissions without requiring full user registration. This is useful for:
Virtual users created this way are marked as virtual accounts and work across Issues, Feature Requests, and Support Tickets.
Validation Rules:
email: format must match RFC 5322 email format. Invalid emails will fall back to anonymous access.discord_id: format must be numeric (digits only). Invalid discord_ids will fall back to anonymous access.Personal Access Tokens provide enhanced security and can be created and managed in your account settings. They are ideal for API integrations, automated scripts, and CI/CD pipelines. Tokens can have different permissions, including:
| Name | Type | Description |
|---|---|---|
| project_id required | string | |
| release_id required | string |
| Name | Type | Description |
|---|---|---|
| platform optional | string | Platform to download (e.g., “windows”, “macos”, “linux”). If provided, redirects to download URL. |
| Name | Type | Description |
|---|---|---|
| BetaHub-Project-ID required | string | BetaHub project ID, the same as the project_id |
curl \ -H "Authorization: Bearer YOUR_API_TOKEN" \ -H "BetaHub-Project-ID: 123" \ "https://app.betahub.io/projects/123/releases/123/download?platform=example"
require "net/http" uri = URI("https://app.betahub.io/projects/123/releases/123/download?platform=example") http = Net::HTTP.new(uri.host, uri.port) http.use_ssl = true request = Net::HTTP::Get.new(uri) request["Authorization"] = "Bearer YOUR_API_TOKEN" request["BetaHub-Project-ID"] = "123" response = http.request(request) puts response.body
import requests response = requests.get( "https://app.betahub.io/projects/123/releases/123/download?platform=example", headers={"Authorization": "Bearer YOUR_API_TOKEN", "BetaHub-Project-ID": "123"} ) print(response.json())
const response = await fetch("https://app.betahub.io/projects/123/releases/123/download?platform=example", { headers: { "Authorization": "Bearer YOUR_API_TOKEN", "BetaHub-Project-ID": "123" } }); const data = await response.json();
HttpClient client = HttpClient.newHttpClient(); HttpRequest request = HttpRequest.newBuilder() .uri(URI.create("https://app.betahub.io/projects/123/releases/123/download?platform=example")) .header("Authorization", "Bearer YOUR_API_TOKEN") .header("BetaHub-Project-ID", "123") .GET() .build(); HttpResponse<String> response = client.send( request, HttpResponse.BodyHandlers.ofString()); System.out.println(response.body());
{
"available_platforms": [
{
"platform": "windows",
"download_url": "https://app.betahub.io/projects/1/releases/rel-123abc/download?platform=windows",
"download_count": 42
},
{
"platform": "macos",
"download_url": "https://app.betahub.io/projects/1/releases/rel-123abc/download?platform=macos",
"download_count": 18
}
]
}
{
"error": "string",
"status": "string"
}
{
"error": "string",
"status": "string"
}
Authorization header for API access. Supports multiple authentication methods:
FormUser anonymous - for public operationsFormUser tkn-{token} - for authenticated operations with legacy tokensFormUser tkn-{token},email:{email} - creates/links virtual user by emailFormUser tkn-{token},discord_id:{discord_id} - creates/links virtual user by Discord IDFormUser tkn-{token},{jwt_token} - user identification with JWT token (legacy)Bearer YOUR_TOKEN_HERE - recommended for API integrationsWhen using email: or discord_id: formats with FormUser tokens, the system automatically creates or reuses virtual users. Virtual users are accounts created on-the-fly for form submissions without requiring full user registration. This is useful for:
Virtual users created this way are marked as virtual accounts and work across Issues, Feature Requests, and Support Tickets.
Validation Rules:
email: format must match RFC 5322 email format. Invalid emails will fall back to anonymous access.discord_id: format must be numeric (digits only). Invalid discord_ids will fall back to anonymous access.Personal Access Tokens provide enhanced security and can be created and managed in your account settings. They are ideal for API integrations, automated scripts, and CI/CD pipelines. Tokens can have different permissions, including:
| Name | Type | Description |
|---|---|---|
| project_id required | string | |
| release_id required | string |
| Name | Type | Description |
|---|---|---|
| BetaHub-Project-ID required | string | BetaHub project ID, the same as the project_id |
curl \ -X POST \ -H "Authorization: Bearer YOUR_API_TOKEN" \ -H "BetaHub-Project-ID: 123" \ "https://app.betahub.io/projects/123/releases/123/publish.json"
require "net/http" uri = URI("https://app.betahub.io/projects/123/releases/123/publish.json") http = Net::HTTP.new(uri.host, uri.port) http.use_ssl = true request = Net::HTTP::Post.new(uri) request["Authorization"] = "Bearer YOUR_API_TOKEN" request["BetaHub-Project-ID"] = "123" response = http.request(request) puts response.body
import requests response = requests.post( "https://app.betahub.io/projects/123/releases/123/publish.json", headers={"Authorization": "Bearer YOUR_API_TOKEN", "BetaHub-Project-ID": "123"} ) print(response.json())
const response = await fetch("https://app.betahub.io/projects/123/releases/123/publish.json", { method: "POST", headers: { "Authorization": "Bearer YOUR_API_TOKEN", "BetaHub-Project-ID": "123" } }); const data = await response.json();
HttpClient client = HttpClient.newHttpClient(); HttpRequest request = HttpRequest.newBuilder() .uri(URI.create("https://app.betahub.io/projects/123/releases/123/publish.json")) .header("Authorization", "Bearer YOUR_API_TOKEN") .header("BetaHub-Project-ID", "123") .method("POST", HttpRequest.BodyPublishers.noBody()) .build(); HttpResponse<String> response = client.send( request, HttpResponse.BodyHandlers.ofString()); System.out.println(response.body());
{
"id": "rel-123abc",
"label": "v1.0.0",
"summary": "Initial release",
"description": "First stable version",
"status": "published",
"active": true,
"release_type": "regular",
"created_at": "2024-10-03T12:34:56Z",
"updated_at": "2024-10-03T15:20:30Z",
"download_links": [],
"attachments_count": 0,
"url": "https://app.betahub.io/projects/1/releases/rel-123abc"
}
{
"error": "string",
"status": "string"
}
{
"error": "string",
"status": "string"
}
Authorization header for API access. Supports multiple authentication methods:
FormUser anonymous - for public operationsFormUser tkn-{token} - for authenticated operations with legacy tokensFormUser tkn-{token},email:{email} - creates/links virtual user by emailFormUser tkn-{token},discord_id:{discord_id} - creates/links virtual user by Discord IDFormUser tkn-{token},{jwt_token} - user identification with JWT token (legacy)Bearer YOUR_TOKEN_HERE - recommended for API integrationsWhen using email: or discord_id: formats with FormUser tokens, the system automatically creates or reuses virtual users. Virtual users are accounts created on-the-fly for form submissions without requiring full user registration. This is useful for:
Virtual users created this way are marked as virtual accounts and work across Issues, Feature Requests, and Support Tickets.
Validation Rules:
email: format must match RFC 5322 email format. Invalid emails will fall back to anonymous access.discord_id: format must be numeric (digits only). Invalid discord_ids will fall back to anonymous access.Personal Access Tokens provide enhanced security and can be created and managed in your account settings. They are ideal for API integrations, automated scripts, and CI/CD pipelines. Tokens can have different permissions, including:
| Name | Type | Description |
|---|---|---|
| project_id required | string | |
| release_id required | string |
| Name | Type | Description |
|---|---|---|
| BetaHub-Project-ID required | string | BetaHub project ID, the same as the project_id |
curl \ -X POST \ -H "Authorization: Bearer YOUR_API_TOKEN" \ -H "BetaHub-Project-ID: 123" \ "https://app.betahub.io/projects/123/releases/123/archive.json"
require "net/http" uri = URI("https://app.betahub.io/projects/123/releases/123/archive.json") http = Net::HTTP.new(uri.host, uri.port) http.use_ssl = true request = Net::HTTP::Post.new(uri) request["Authorization"] = "Bearer YOUR_API_TOKEN" request["BetaHub-Project-ID"] = "123" response = http.request(request) puts response.body
import requests response = requests.post( "https://app.betahub.io/projects/123/releases/123/archive.json", headers={"Authorization": "Bearer YOUR_API_TOKEN", "BetaHub-Project-ID": "123"} ) print(response.json())
const response = await fetch("https://app.betahub.io/projects/123/releases/123/archive.json", { method: "POST", headers: { "Authorization": "Bearer YOUR_API_TOKEN", "BetaHub-Project-ID": "123" } }); const data = await response.json();
HttpClient client = HttpClient.newHttpClient(); HttpRequest request = HttpRequest.newBuilder() .uri(URI.create("https://app.betahub.io/projects/123/releases/123/archive.json")) .header("Authorization", "Bearer YOUR_API_TOKEN") .header("BetaHub-Project-ID", "123") .method("POST", HttpRequest.BodyPublishers.noBody()) .build(); HttpResponse<String> response = client.send( request, HttpResponse.BodyHandlers.ofString()); System.out.println(response.body());
{
"id": "rel-123abc",
"label": "v0.9.0",
"summary": "Beta release",
"description": "Old beta version",
"status": "archived",
"active": false,
"release_type": "regular",
"created_at": "2024-09-01T12:34:56Z",
"updated_at": "2024-10-03T15:20:30Z",
"download_links": [],
"attachments_count": 0,
"url": "https://app.betahub.io/projects/1/releases/rel-123abc"
}
{
"error": "string",
"status": "string"
}
{
"error": "string",
"status": "string"
}
{
"error": "Cannot archive the only published release for this project."
}
Authorization header for API access. Supports multiple authentication methods:
FormUser anonymous - for public operationsFormUser tkn-{token} - for authenticated operations with legacy tokensFormUser tkn-{token},email:{email} - creates/links virtual user by emailFormUser tkn-{token},discord_id:{discord_id} - creates/links virtual user by Discord IDFormUser tkn-{token},{jwt_token} - user identification with JWT token (legacy)Bearer YOUR_TOKEN_HERE - recommended for API integrationsWhen using email: or discord_id: formats with FormUser tokens, the system automatically creates or reuses virtual users. Virtual users are accounts created on-the-fly for form submissions without requiring full user registration. This is useful for:
Virtual users created this way are marked as virtual accounts and work across Issues, Feature Requests, and Support Tickets.
Validation Rules:
email: format must match RFC 5322 email format. Invalid emails will fall back to anonymous access.discord_id: format must be numeric (digits only). Invalid discord_ids will fall back to anonymous access.Personal Access Tokens provide enhanced security and can be created and managed in your account settings. They are ideal for API integrations, automated scripts, and CI/CD pipelines. Tokens can have different permissions, including:
| Name | Type | Description |
|---|---|---|
| project_id required | string | |
| release_id required | string |
| Name | Type | Description |
|---|---|---|
| BetaHub-Project-ID required | string | BetaHub project ID, the same as the project_id |
curl \ -X POST \ -H "Authorization: Bearer YOUR_API_TOKEN" \ -H "BetaHub-Project-ID: 123" \ "https://app.betahub.io/projects/123/releases/123/restore.json"
require "net/http" uri = URI("https://app.betahub.io/projects/123/releases/123/restore.json") http = Net::HTTP.new(uri.host, uri.port) http.use_ssl = true request = Net::HTTP::Post.new(uri) request["Authorization"] = "Bearer YOUR_API_TOKEN" request["BetaHub-Project-ID"] = "123" response = http.request(request) puts response.body
import requests response = requests.post( "https://app.betahub.io/projects/123/releases/123/restore.json", headers={"Authorization": "Bearer YOUR_API_TOKEN", "BetaHub-Project-ID": "123"} ) print(response.json())
const response = await fetch("https://app.betahub.io/projects/123/releases/123/restore.json", { method: "POST", headers: { "Authorization": "Bearer YOUR_API_TOKEN", "BetaHub-Project-ID": "123" } }); const data = await response.json();
HttpClient client = HttpClient.newHttpClient(); HttpRequest request = HttpRequest.newBuilder() .uri(URI.create("https://app.betahub.io/projects/123/releases/123/restore.json")) .header("Authorization", "Bearer YOUR_API_TOKEN") .header("BetaHub-Project-ID", "123") .method("POST", HttpRequest.BodyPublishers.noBody()) .build(); HttpResponse<String> response = client.send( request, HttpResponse.BodyHandlers.ofString()); System.out.println(response.body());
{
"id": "rel-123abc",
"label": "v0.9.0",
"summary": "Beta release",
"description": "Old beta version",
"status": "published",
"active": true,
"release_type": "regular",
"created_at": "2024-09-01T12:34:56Z",
"updated_at": "2024-10-03T15:20:30Z",
"download_links": [],
"attachments_count": 0,
"url": "https://app.betahub.io/projects/1/releases/rel-123abc"
}
{
"error": "string",
"status": "string"
}
{
"error": "string",
"status": "string"
}
{
"error": "string",
"status": "string"
}
Authorization header for API access. Supports multiple authentication methods:
FormUser anonymous - for public operationsFormUser tkn-{token} - for authenticated operations with legacy tokensFormUser tkn-{token},email:{email} - creates/links virtual user by emailFormUser tkn-{token},discord_id:{discord_id} - creates/links virtual user by Discord IDFormUser tkn-{token},{jwt_token} - user identification with JWT token (legacy)Bearer YOUR_TOKEN_HERE - recommended for API integrationsWhen using email: or discord_id: formats with FormUser tokens, the system automatically creates or reuses virtual users. Virtual users are accounts created on-the-fly for form submissions without requiring full user registration. This is useful for:
Virtual users created this way are marked as virtual accounts and work across Issues, Feature Requests, and Support Tickets.
Validation Rules:
email: format must match RFC 5322 email format. Invalid emails will fall back to anonymous access.discord_id: format must be numeric (digits only). Invalid discord_ids will fall back to anonymous access.Personal Access Tokens provide enhanced security and can be created and managed in your account settings. They are ideal for API integrations, automated scripts, and CI/CD pipelines. Tokens can have different permissions, including:
| Name | Type | Description |
|---|---|---|
| project_id required | string |
| Name | Type | Description |
|---|---|---|
| BetaHub-Project-ID required | string | BetaHub project ID, the same as the project_id |
curl \ -H "Authorization: Bearer YOUR_API_TOKEN" \ -H "BetaHub-Project-ID: 123" \ "https://app.betahub.io/projects/123/game_facts.json"
require "net/http" uri = URI("https://app.betahub.io/projects/123/game_facts.json") http = Net::HTTP.new(uri.host, uri.port) http.use_ssl = true request = Net::HTTP::Get.new(uri) request["Authorization"] = "Bearer YOUR_API_TOKEN" request["BetaHub-Project-ID"] = "123" response = http.request(request) puts response.body
import requests response = requests.get( "https://app.betahub.io/projects/123/game_facts.json", headers={"Authorization": "Bearer YOUR_API_TOKEN", "BetaHub-Project-ID": "123"} ) print(response.json())
const response = await fetch("https://app.betahub.io/projects/123/game_facts.json", { headers: { "Authorization": "Bearer YOUR_API_TOKEN", "BetaHub-Project-ID": "123" } }); const data = await response.json();
HttpClient client = HttpClient.newHttpClient(); HttpRequest request = HttpRequest.newBuilder() .uri(URI.create("https://app.betahub.io/projects/123/game_facts.json")) .header("Authorization", "Bearer YOUR_API_TOKEN") .header("BetaHub-Project-ID", "123") .GET() .build(); HttpResponse<String> response = client.send( request, HttpResponse.BodyHandlers.ofString()); System.out.println(response.body());
{
"description": "A fantasy RPG set in a magical world",
"genre": "Action RPG",
"target_audience": "Teen",
"platforms": [
"PC",
"PlayStation",
"Xbox"
],
"core_mechanics": {
"key_features": [
"Magic system",
"Character progression",
"Crafting"
],
"game_modes": [
"Single Player",
"Cooperative"
],
"controls": {
"pc": {
"move": "WASD",
"attack": "Left Click"
},
"console": {
"move": "Left Stick",
"attack": "X Button"
}
}
},
"technical_specifications": {
"supported_platforms": [
"Windows",
"Linux",
"macOS"
],
"minimum_system_requirements": {
"ram": "8GB",
"cpu": "Intel i5",
"gpu": "GTX 1060"
}
},
"glossary": {
"items": [
{
"term": "Mana Potion",
"definition": "Restores magical energy"
}
],
"characters": [
{
"term": "Elder Mage",
"definition": "Wise spellcaster and quest giver"
}
],
"events": [],
"locations": [],
"other_terms": []
},
"project": {
"id": "pr-123456",
"name": "My Fantasy Game"
},
"meta": {
"created_at": "2024-10-03T12:34:56Z",
"updated_at": "2024-10-03T14:22:10Z"
}
}
{
"error": "string",
"status": "string"
}
{
"error": "string",
"status": "string"
}
Authorization header for API access. Supports multiple authentication methods:
FormUser anonymous - for public operationsFormUser tkn-{token} - for authenticated operations with legacy tokensFormUser tkn-{token},email:{email} - creates/links virtual user by emailFormUser tkn-{token},discord_id:{discord_id} - creates/links virtual user by Discord IDFormUser tkn-{token},{jwt_token} - user identification with JWT token (legacy)Bearer YOUR_TOKEN_HERE - recommended for API integrationsWhen using email: or discord_id: formats with FormUser tokens, the system automatically creates or reuses virtual users. Virtual users are accounts created on-the-fly for form submissions without requiring full user registration. This is useful for:
Virtual users created this way are marked as virtual accounts and work across Issues, Feature Requests, and Support Tickets.
Validation Rules:
email: format must match RFC 5322 email format. Invalid emails will fall back to anonymous access.discord_id: format must be numeric (digits only). Invalid discord_ids will fall back to anonymous access.Personal Access Tokens provide enhanced security and can be created and managed in your account settings. They are ideal for API integrations, automated scripts, and CI/CD pipelines. Tokens can have different permissions, including:
| Name | Type | Description |
|---|---|---|
| project_id required | string |
| Name | Type | Description |
|---|---|---|
| BetaHub-Project-ID required | string | BetaHub project ID, the same as the project_id |
curl \ -X PATCH \ -H "Authorization: Bearer YOUR_API_TOKEN" \ -H "BetaHub-Project-ID: 123" \ -H "Content-Type: application/json" \ -d '{ "game_fact": { "description": "string", "genre": "string", "target_audience": "string", "ui_ux_considerations": "string", "platforms": [ "string" ], "core_mechanics": { "key_features": [ "string" ], "game_modes": [ "string" ], "controls": { "pc": {}, "console": {} } }, "technical_specifications": { "supported_platforms": [ "string" ], "minimum_system_requirements": {} }, "game_progression": { "level_design": "string", "progression_system": "string" }, "bug_reporting_guidelines": { "critical_components": [ "string" ], "non_critical_components": [ "string" ], "known_bugs": [ "string" ] }, "glossary": { "items": [ {} ], "characters": [ {} ], "events": [ {} ], "locations": [ {} ], "other_terms": [ {} ] }, "save_load_system": { "save_method": "string", "known_issues": [ "string" ] }, "multiplayer_online_features": { "supported_modes": [ "string" ], "networking": { "server_type": "string", "known_issues": [ null ] } }, "localization": { "supported_languages": [ "string" ], "known_issues": [ "string" ] } } }' \ "https://app.betahub.io/projects/123/game_facts.json"
require "net/http" require "json" uri = URI("https://app.betahub.io/projects/123/game_facts.json") http = Net::HTTP.new(uri.host, uri.port) http.use_ssl = true request = Net::HTTP::Patch.new(uri) request["Authorization"] = "Bearer YOUR_API_TOKEN" request["BetaHub-Project-ID"] = "123" request["Content-Type"] = "application/json" request.body = { "game_fact": { "description": "string", "genre": "string", "target_audience": "string", "ui_ux_considerations": "string", "platforms": [ "string" ], "core_mechanics": { "key_features": [ "string" ], "game_modes": [ "string" ], "controls": { "pc": {}, "console": {} } }, "technical_specifications": { "supported_platforms": [ "string" ], "minimum_system_requirements": {} }, "game_progression": { "level_design": "string", "progression_system": "string" }, "bug_reporting_guidelines": { "critical_components": [ "string" ], "non_critical_components": [ "string" ], "known_bugs": [ "string" ] }, "glossary": { "items": [ {} ], "characters": [ {} ], "events": [ {} ], "locations": [ {} ], "other_terms": [ {} ] }, "save_load_system": { "save_method": "string", "known_issues": [ "string" ] }, "multiplayer_online_features": { "supported_modes": [ "string" ], "networking": { "server_type": "string", "known_issues": [ null ] } }, "localization": { "supported_languages": [ "string" ], "known_issues": [ "string" ] } } } response = http.request(request) puts response.body
import requests response = requests.patch( "https://app.betahub.io/projects/123/game_facts.json", headers={"Authorization": "Bearer YOUR_API_TOKEN", "BetaHub-Project-ID": "123"}, json={ "game_fact": { "description": "string", "genre": "string", "target_audience": "string", "ui_ux_considerations": "string", "platforms": [ "string" ], "core_mechanics": { "key_features": [ "string" ], "game_modes": [ "string" ], "controls": { "pc": {}, "console": {} } }, "technical_specifications": { "supported_platforms": [ "string" ], "minimum_system_requirements": {} }, "game_progression": { "level_design": "string", "progression_system": "string" }, "bug_reporting_guidelines": { "critical_components": [ "string" ], "non_critical_components": [ "string" ], "known_bugs": [ "string" ] }, "glossary": { "items": [ {} ], "characters": [ {} ], "events": [ {} ], "locations": [ {} ], "other_terms": [ {} ] }, "save_load_system": { "save_method": "string", "known_issues": [ "string" ] }, "multiplayer_online_features": { "supported_modes": [ "string" ], "networking": { "server_type": "string", "known_issues": [ null ] } }, "localization": { "supported_languages": [ "string" ], "known_issues": [ "string" ] } } } ) print(response.json())
const response = await fetch("https://app.betahub.io/projects/123/game_facts.json", { method: "PATCH", headers: { "Authorization": "Bearer YOUR_API_TOKEN", "BetaHub-Project-ID": "123", "Content-Type": "application/json" }, body: JSON.stringify({ "game_fact": { "description": "string", "genre": "string", "target_audience": "string", "ui_ux_considerations": "string", "platforms": [ "string" ], "core_mechanics": { "key_features": [ "string" ], "game_modes": [ "string" ], "controls": { "pc": {}, "console": {} } }, "technical_specifications": { "supported_platforms": [ "string" ], "minimum_system_requirements": {} }, "game_progression": { "level_design": "string", "progression_system": "string" }, "bug_reporting_guidelines": { "critical_components": [ "string" ], "non_critical_components": [ "string" ], "known_bugs": [ "string" ] }, "glossary": { "items": [ {} ], "characters": [ {} ], "events": [ {} ], "locations": [ {} ], "other_terms": [ {} ] }, "save_load_system": { "save_method": "string", "known_issues": [ "string" ] }, "multiplayer_online_features": { "supported_modes": [ "string" ], "networking": { "server_type": "string", "known_issues": [ null ] } }, "localization": { "supported_languages": [ "string" ], "known_issues": [ "string" ] } } }) }); const data = await response.json();
HttpClient client = HttpClient.newHttpClient(); HttpRequest request = HttpRequest.newBuilder() .uri(URI.create("https://app.betahub.io/projects/123/game_facts.json")) .header("Authorization", "Bearer YOUR_API_TOKEN") .header("BetaHub-Project-ID", "123") .header("Content-Type", "application/json") .PATCH(HttpRequest.BodyPublishers.ofString("{\"game_fact\":{\"description\":\"string\",\"genre\":\"string\",\"target_audience\":\"string\",\"ui_ux_considerations\":\"string\",\"platforms\":[\"string\"],\"core_mechanics\":{\"key_features\":[\"string\"],\"game_modes\":[\"string\"],\"controls\":{\"pc\":{},\"console\":{}}},\"technical_specifications\":{\"supported_platforms\":[\"string\"],\"minimum_system_requirements\":{}},\"game_progression\":{\"level_design\":\"string\",\"progression_system\":\"string\"},\"bug_reporting_guidelines\":{\"critical_components\":[\"string\"],\"non_critical_components\":[\"string\"],\"known_bugs\":[\"string\"]},\"glossary\":{\"items\":[{}],\"characters\":[{}],\"events\":[{}],\"locations\":[{}],\"other_terms\":[{}]},\"save_load_system\":{\"save_method\":\"string\",\"known_issues\":[\"string\"]},\"multiplayer_online_features\":{\"supported_modes\":[\"string\"],\"networking\":{\"server_type\":\"string\",\"known_issues\":[null]}},\"localization\":{\"supported_languages\":[\"string\"],\"known_issues\":[\"string\"]}}}")) .build(); HttpResponse<String> response = client.send( request, HttpResponse.BodyHandlers.ofString()); System.out.println(response.body());
{
"game_fact": {
"description": "string",
"genre": "string",
"target_audience": "string",
"ui_ux_considerations": "string",
"platforms": [
"string"
],
"core_mechanics": {
"key_features": [
"string"
],
"game_modes": [
"string"
],
"controls": {
"pc": {},
"console": {}
}
},
"technical_specifications": {
"supported_platforms": [
"string"
],
"minimum_system_requirements": {}
},
"game_progression": {
"level_design": "string",
"progression_system": "string"
},
"bug_reporting_guidelines": {
"critical_components": [
"string"
],
"non_critical_components": [
"string"
],
"known_bugs": [
"string"
]
},
"glossary": {
"items": [
{}
],
"characters": [
{}
],
"events": [
{}
],
"locations": [
{}
],
"other_terms": [
{}
]
},
"save_load_system": {
"save_method": "string",
"known_issues": [
"string"
]
},
"multiplayer_online_features": {
"supported_modes": [
"string"
],
"networking": {
"server_type": "string",
"known_issues": [
null
]
}
},
"localization": {
"supported_languages": [
"string"
],
"known_issues": [
"string"
]
}
}
}
{
"description": "Updated game description",
"genre": "Action RPG",
"target_audience": "Teen",
"platforms": [
"PC",
"PlayStation"
],
"core_mechanics": {
"key_features": [
"Updated feature"
],
"game_modes": [
"Single Player"
]
},
"project": {
"id": "pr-123456",
"name": "My Fantasy Game"
},
"meta": {
"created_at": "2024-10-03T12:34:56Z",
"updated_at": "2024-10-03T16:45:30Z"
}
}
{
"error": "string",
"status": "string"
}
{
"error": "string",
"status": "string"
}
{
"errors": [
"Description is too long (maximum is 1000 characters)"
]
}
playtime_session[platform]=ios to associate the playtime session with the iOS platform. The returned is a uuid that can be used to update the playtime session using the PUT endpoint.Authorization header for API access. Supports multiple authentication methods:
FormUser anonymous - for public operationsFormUser tkn-{token} - for authenticated operations with legacy tokensFormUser tkn-{token},email:{email} - creates/links virtual user by emailFormUser tkn-{token},discord_id:{discord_id} - creates/links virtual user by Discord IDFormUser tkn-{token},{jwt_token} - user identification with JWT token (legacy)Bearer YOUR_TOKEN_HERE - recommended for API integrationsWhen using email: or discord_id: formats with FormUser tokens, the system automatically creates or reuses virtual users. Virtual users are accounts created on-the-fly for form submissions without requiring full user registration. This is useful for:
Virtual users created this way are marked as virtual accounts and work across Issues, Feature Requests, and Support Tickets.
Validation Rules:
email: format must match RFC 5322 email format. Invalid emails will fall back to anonymous access.discord_id: format must be numeric (digits only). Invalid discord_ids will fall back to anonymous access.Personal Access Tokens provide enhanced security and can be created and managed in your account settings. They are ideal for API integrations, automated scripts, and CI/CD pipelines. Tokens can have different permissions, including:
| Name | Type | Description |
|---|---|---|
| project_id required | string |
| Name | Type | Description |
|---|---|---|
| BetaHub-Project-ID required | string | BetaHub project ID, the same as the project_id |
curl \ -X POST \ -H "Authorization: Bearer YOUR_API_TOKEN" \ -H "BetaHub-Project-ID: 123" \ -H "Content-Type: application/json" \ -d '{ "playtime_session[tags]": "string" }' \ "https://app.betahub.io/projects/123/playtime_sessions"
require "net/http" require "json" uri = URI("https://app.betahub.io/projects/123/playtime_sessions") http = Net::HTTP.new(uri.host, uri.port) http.use_ssl = true request = Net::HTTP::Post.new(uri) request["Authorization"] = "Bearer YOUR_API_TOKEN" request["BetaHub-Project-ID"] = "123" request["Content-Type"] = "application/json" request.body = { "playtime_session[tags]": "string" } response = http.request(request) puts response.body
import requests response = requests.post( "https://app.betahub.io/projects/123/playtime_sessions", headers={"Authorization": "Bearer YOUR_API_TOKEN", "BetaHub-Project-ID": "123"}, json={ "playtime_session[tags]": "string" } ) print(response.json())
const response = await fetch("https://app.betahub.io/projects/123/playtime_sessions", { method: "POST", headers: { "Authorization": "Bearer YOUR_API_TOKEN", "BetaHub-Project-ID": "123", "Content-Type": "application/json" }, body: JSON.stringify({ "playtime_session[tags]": "string" }) }); const data = await response.json();
HttpClient client = HttpClient.newHttpClient(); HttpRequest request = HttpRequest.newBuilder() .uri(URI.create("https://app.betahub.io/projects/123/playtime_sessions")) .header("Authorization", "Bearer YOUR_API_TOKEN") .header("BetaHub-Project-ID", "123") .header("Content-Type", "application/json") .POST(HttpRequest.BodyPublishers.ofString("{\"playtime_session[tags]\":\"string\"}")) .build(); HttpResponse<String> response = client.send( request, HttpResponse.BodyHandlers.ofString()); System.out.println(response.body());
{
"playtime_session[tags]": "string"
}
{
"playtime_session[tags]": "platform=ios"
}
Authorization header for API access. Supports multiple authentication methods:
FormUser anonymous - for public operationsFormUser tkn-{token} - for authenticated operations with legacy tokensFormUser tkn-{token},email:{email} - creates/links virtual user by emailFormUser tkn-{token},discord_id:{discord_id} - creates/links virtual user by Discord IDFormUser tkn-{token},{jwt_token} - user identification with JWT token (legacy)Bearer YOUR_TOKEN_HERE - recommended for API integrationsWhen using email: or discord_id: formats with FormUser tokens, the system automatically creates or reuses virtual users. Virtual users are accounts created on-the-fly for form submissions without requiring full user registration. This is useful for:
Virtual users created this way are marked as virtual accounts and work across Issues, Feature Requests, and Support Tickets.
Validation Rules:
email: format must match RFC 5322 email format. Invalid emails will fall back to anonymous access.discord_id: format must be numeric (digits only). Invalid discord_ids will fall back to anonymous access.Personal Access Tokens provide enhanced security and can be created and managed in your account settings. They are ideal for API integrations, automated scripts, and CI/CD pipelines. Tokens can have different permissions, including:
| Name | Type | Description |
|---|---|---|
| project_id required | string | |
| playtime_session_id required | string |
| Name | Type | Description |
|---|---|---|
| BetaHub-Project-ID required | string | BetaHub project ID, the same as the project_id |
curl \ -X PUT \ -H "Authorization: Bearer YOUR_API_TOKEN" \ -H "BetaHub-Project-ID: 123" \ "https://app.betahub.io/projects/123/playtime_sessions/123"
require "net/http" uri = URI("https://app.betahub.io/projects/123/playtime_sessions/123") http = Net::HTTP.new(uri.host, uri.port) http.use_ssl = true request = Net::HTTP::Put.new(uri) request["Authorization"] = "Bearer YOUR_API_TOKEN" request["BetaHub-Project-ID"] = "123" response = http.request(request) puts response.body
import requests response = requests.put( "https://app.betahub.io/projects/123/playtime_sessions/123", headers={"Authorization": "Bearer YOUR_API_TOKEN", "BetaHub-Project-ID": "123"} ) print(response.json())
const response = await fetch("https://app.betahub.io/projects/123/playtime_sessions/123", { method: "PUT", headers: { "Authorization": "Bearer YOUR_API_TOKEN", "BetaHub-Project-ID": "123" } }); const data = await response.json();
HttpClient client = HttpClient.newHttpClient(); HttpRequest request = HttpRequest.newBuilder() .uri(URI.create("https://app.betahub.io/projects/123/playtime_sessions/123")) .header("Authorization", "Bearer YOUR_API_TOKEN") .header("BetaHub-Project-ID", "123") .method("PUT", HttpRequest.BodyPublishers.noBody()) .build(); HttpResponse<String> response = client.send( request, HttpResponse.BodyHandlers.ofString()); System.out.println(response.body());
{
"id": "1234abc"
}
{
"error": "string",
"status": "string"
}
{
"error": "string",
"status": "string"
}
Authorization header for API access. Supports multiple authentication methods:
FormUser anonymous - for public operationsFormUser tkn-{token} - for authenticated operations with legacy tokensFormUser tkn-{token},email:{email} - creates/links virtual user by emailFormUser tkn-{token},discord_id:{discord_id} - creates/links virtual user by Discord IDFormUser tkn-{token},{jwt_token} - user identification with JWT token (legacy)Bearer YOUR_TOKEN_HERE - recommended for API integrationsWhen using email: or discord_id: formats with FormUser tokens, the system automatically creates or reuses virtual users. Virtual users are accounts created on-the-fly for form submissions without requiring full user registration. This is useful for:
Virtual users created this way are marked as virtual accounts and work across Issues, Feature Requests, and Support Tickets.
Validation Rules:
email: format must match RFC 5322 email format. Invalid emails will fall back to anonymous access.discord_id: format must be numeric (digits only). Invalid discord_ids will fall back to anonymous access.Personal Access Tokens provide enhanced security and can be created and managed in your account settings. They are ideal for API integrations, automated scripts, and CI/CD pipelines. Tokens can have different permissions, including:
| Name | Type | Description |
|---|---|---|
| project_id required | string |
| Name | Type | Description |
|---|---|---|
| applies_to optional | string |
Filter by entity type the custom fields apply to
issue
feature_request
ticket
Default:
issue |
| page optional | integer | Page number for pagination (default: 1) |
| Name | Type | Description |
|---|---|---|
| BetaHub-Project-ID required | string | BetaHub project ID, the same as the project_id |
curl \ -H "Authorization: Bearer YOUR_API_TOKEN" \ -H "BetaHub-Project-ID: 123" \ "https://app.betahub.io/projects/123/custom_fields.json?applies_to=issue&page=123"
require "net/http" uri = URI("https://app.betahub.io/projects/123/custom_fields.json?applies_to=issue&page=123") http = Net::HTTP.new(uri.host, uri.port) http.use_ssl = true request = Net::HTTP::Get.new(uri) request["Authorization"] = "Bearer YOUR_API_TOKEN" request["BetaHub-Project-ID"] = "123" response = http.request(request) puts response.body
import requests response = requests.get( "https://app.betahub.io/projects/123/custom_fields.json?applies_to=issue&page=123", headers={"Authorization": "Bearer YOUR_API_TOKEN", "BetaHub-Project-ID": "123"} ) print(response.json())
const response = await fetch("https://app.betahub.io/projects/123/custom_fields.json?applies_to=issue&page=123", { headers: { "Authorization": "Bearer YOUR_API_TOKEN", "BetaHub-Project-ID": "123" } }); const data = await response.json();
HttpClient client = HttpClient.newHttpClient(); HttpRequest request = HttpRequest.newBuilder() .uri(URI.create("https://app.betahub.io/projects/123/custom_fields.json?applies_to=issue&page=123")) .header("Authorization", "Bearer YOUR_API_TOKEN") .header("BetaHub-Project-ID", "123") .GET() .build(); HttpResponse<String> response = client.send( request, HttpResponse.BodyHandlers.ofString()); System.out.println(response.body());
{
"custom_fields": [
{
"id": 0,
"ident": "string",
"name": "string",
"field_type": "string",
"required": true,
"tester_settable": true,
"tester_viewable": true,
"options": {},
"applies_to": "issue",
"created_at": "2026-03-12T10:30:00Z",
"updated_at": "2026-03-12T10:30:00Z"
}
],
"custom_issue_fields": [
{
"id": 0,
"ident": "string",
"name": "string",
"field_type": "string",
"required": true,
"tester_settable": true,
"tester_viewable": true,
"options": {},
"applies_to": "issue",
"created_at": "2026-03-12T10:30:00Z",
"updated_at": "2026-03-12T10:30:00Z"
}
],
"pagination": {
"current_page": 0,
"total_pages": 0,
"total_count": 0,
"per_page": 0
},
"project_id": 0,
"applies_to": "string"
}
{
"error": "string",
"status": "string"
}
Authorization header for API access. Supports multiple authentication methods:
FormUser anonymous - for public operationsFormUser tkn-{token} - for authenticated operations with legacy tokensFormUser tkn-{token},email:{email} - creates/links virtual user by emailFormUser tkn-{token},discord_id:{discord_id} - creates/links virtual user by Discord IDFormUser tkn-{token},{jwt_token} - user identification with JWT token (legacy)Bearer YOUR_TOKEN_HERE - recommended for API integrationsWhen using email: or discord_id: formats with FormUser tokens, the system automatically creates or reuses virtual users. Virtual users are accounts created on-the-fly for form submissions without requiring full user registration. This is useful for:
Virtual users created this way are marked as virtual accounts and work across Issues, Feature Requests, and Support Tickets.
Validation Rules:
email: format must match RFC 5322 email format. Invalid emails will fall back to anonymous access.discord_id: format must be numeric (digits only). Invalid discord_ids will fall back to anonymous access.Personal Access Tokens provide enhanced security and can be created and managed in your account settings. They are ideal for API integrations, automated scripts, and CI/CD pipelines. Tokens can have different permissions, including:
| Name | Type | Description |
|---|---|---|
| project_id required | string |
| Name | Type | Description |
|---|---|---|
| BetaHub-Project-ID required | string | BetaHub project ID, the same as the project_id |
curl \ -H "Authorization: Bearer YOUR_API_TOKEN" \ -H "BetaHub-Project-ID: 123" \ "https://app.betahub.io/projects/123/issue_statuses.json"
require "net/http" uri = URI("https://app.betahub.io/projects/123/issue_statuses.json") http = Net::HTTP.new(uri.host, uri.port) http.use_ssl = true request = Net::HTTP::Get.new(uri) request["Authorization"] = "Bearer YOUR_API_TOKEN" request["BetaHub-Project-ID"] = "123" response = http.request(request) puts response.body
import requests response = requests.get( "https://app.betahub.io/projects/123/issue_statuses.json", headers={"Authorization": "Bearer YOUR_API_TOKEN", "BetaHub-Project-ID": "123"} ) print(response.json())
const response = await fetch("https://app.betahub.io/projects/123/issue_statuses.json", { headers: { "Authorization": "Bearer YOUR_API_TOKEN", "BetaHub-Project-ID": "123" } }); const data = await response.json();
HttpClient client = HttpClient.newHttpClient(); HttpRequest request = HttpRequest.newBuilder() .uri(URI.create("https://app.betahub.io/projects/123/issue_statuses.json")) .header("Authorization", "Bearer YOUR_API_TOKEN") .header("BetaHub-Project-ID", "123") .GET() .build(); HttpResponse<String> response = client.send( request, HttpResponse.BodyHandlers.ofString()); System.out.println(response.body());
{
"issue_statuses": [
{
"key": "string",
"display_name": "string",
"behavior_category": "in_progress",
"system_status": true
}
]
}
{
"error": "string",
"status": "string"
}
Authorization header for API access. Supports multiple authentication methods:
FormUser anonymous - for public operationsFormUser tkn-{token} - for authenticated operations with legacy tokensFormUser tkn-{token},email:{email} - creates/links virtual user by emailFormUser tkn-{token},discord_id:{discord_id} - creates/links virtual user by Discord IDFormUser tkn-{token},{jwt_token} - user identification with JWT token (legacy)Bearer YOUR_TOKEN_HERE - recommended for API integrationsWhen using email: or discord_id: formats with FormUser tokens, the system automatically creates or reuses virtual users. Virtual users are accounts created on-the-fly for form submissions without requiring full user registration. This is useful for:
Virtual users created this way are marked as virtual accounts and work across Issues, Feature Requests, and Support Tickets.
Validation Rules:
email: format must match RFC 5322 email format. Invalid emails will fall back to anonymous access.discord_id: format must be numeric (digits only). Invalid discord_ids will fall back to anonymous access.Personal Access Tokens provide enhanced security and can be created and managed in your account settings. They are ideal for API integrations, automated scripts, and CI/CD pipelines. Tokens can have different permissions, including:
| Name | Type | Description |
|---|---|---|
| project_id required | string |
| Name | Type | Description |
|---|---|---|
| page optional | integer | Page number for pagination (default: 1) |
| Name | Type | Description |
|---|---|---|
| BetaHub-Project-ID required | string | BetaHub project ID, the same as the project_id |
curl \ -H "Authorization: Bearer YOUR_API_TOKEN" \ -H "BetaHub-Project-ID: 123" \ "https://app.betahub.io/projects/123/issue_tags.json?page=123"
require "net/http" uri = URI("https://app.betahub.io/projects/123/issue_tags.json?page=123") http = Net::HTTP.new(uri.host, uri.port) http.use_ssl = true request = Net::HTTP::Get.new(uri) request["Authorization"] = "Bearer YOUR_API_TOKEN" request["BetaHub-Project-ID"] = "123" response = http.request(request) puts response.body
import requests response = requests.get( "https://app.betahub.io/projects/123/issue_tags.json?page=123", headers={"Authorization": "Bearer YOUR_API_TOKEN", "BetaHub-Project-ID": "123"} ) print(response.json())
const response = await fetch("https://app.betahub.io/projects/123/issue_tags.json?page=123", { headers: { "Authorization": "Bearer YOUR_API_TOKEN", "BetaHub-Project-ID": "123" } }); const data = await response.json();
HttpClient client = HttpClient.newHttpClient(); HttpRequest request = HttpRequest.newBuilder() .uri(URI.create("https://app.betahub.io/projects/123/issue_tags.json?page=123")) .header("Authorization", "Bearer YOUR_API_TOKEN") .header("BetaHub-Project-ID", "123") .GET() .build(); HttpResponse<String> response = client.send( request, HttpResponse.BodyHandlers.ofString()); System.out.println(response.body());
{
"tags": [
{
"id": 0,
"name": "string",
"color": "string",
"description": "string",
"parent_tag_id": 0,
"tag_type": "string",
"created_at": "2026-03-12T10:30:00Z",
"updated_at": "2026-03-12T10:30:00Z",
"sub_tags": [
{}
]
}
],
"project_id": 0,
"pagination": {
"current_page": 0,
"total_pages": 0,
"total_count": 0,
"per_page": 0
}
}
{
"error": "string",
"status": "string"
}
Authorization header for API access. Supports multiple authentication methods:
FormUser anonymous - for public operationsFormUser tkn-{token} - for authenticated operations with legacy tokensFormUser tkn-{token},email:{email} - creates/links virtual user by emailFormUser tkn-{token},discord_id:{discord_id} - creates/links virtual user by Discord IDFormUser tkn-{token},{jwt_token} - user identification with JWT token (legacy)Bearer YOUR_TOKEN_HERE - recommended for API integrationsWhen using email: or discord_id: formats with FormUser tokens, the system automatically creates or reuses virtual users. Virtual users are accounts created on-the-fly for form submissions without requiring full user registration. This is useful for:
Virtual users created this way are marked as virtual accounts and work across Issues, Feature Requests, and Support Tickets.
Validation Rules:
email: format must match RFC 5322 email format. Invalid emails will fall back to anonymous access.discord_id: format must be numeric (digits only). Invalid discord_ids will fall back to anonymous access.Personal Access Tokens provide enhanced security and can be created and managed in your account settings. They are ideal for API integrations, automated scripts, and CI/CD pipelines. Tokens can have different permissions, including:
curl \ -H "Authorization: Bearer YOUR_API_TOKEN" \ "https://app.betahub.io/profiles/me.json"
require "net/http" uri = URI("https://app.betahub.io/profiles/me.json") http = Net::HTTP.new(uri.host, uri.port) http.use_ssl = true request = Net::HTTP::Get.new(uri) request["Authorization"] = "Bearer YOUR_API_TOKEN" response = http.request(request) puts response.body
import requests response = requests.get( "https://app.betahub.io/profiles/me.json", headers={"Authorization": "Bearer YOUR_API_TOKEN"} ) print(response.json())
const response = await fetch("https://app.betahub.io/profiles/me.json", { headers: { "Authorization": "Bearer YOUR_API_TOKEN" } }); const data = await response.json();
HttpClient client = HttpClient.newHttpClient(); HttpRequest request = HttpRequest.newBuilder() .uri(URI.create("https://app.betahub.io/profiles/me.json")) .header("Authorization", "Bearer YOUR_API_TOKEN") .GET() .build(); HttpResponse<String> response = client.send( request, HttpResponse.BodyHandlers.ofString()); System.out.println(response.body());
{
"name": "string",
"roles": [
{
"project": {},
"role": "string"
}
]
}
{
"error": "string",
"status": "string"
}
Authorization header for API access. Supports multiple authentication methods:
FormUser anonymous - for public operationsFormUser tkn-{token} - for authenticated operations with legacy tokensFormUser tkn-{token},email:{email} - creates/links virtual user by emailFormUser tkn-{token},discord_id:{discord_id} - creates/links virtual user by Discord IDFormUser tkn-{token},{jwt_token} - user identification with JWT token (legacy)Bearer YOUR_TOKEN_HERE - recommended for API integrationsWhen using email: or discord_id: formats with FormUser tokens, the system automatically creates or reuses virtual users. Virtual users are accounts created on-the-fly for form submissions without requiring full user registration. This is useful for:
Virtual users created this way are marked as virtual accounts and work across Issues, Feature Requests, and Support Tickets.
Validation Rules:
email: format must match RFC 5322 email format. Invalid emails will fall back to anonymous access.discord_id: format must be numeric (digits only). Invalid discord_ids will fall back to anonymous access.Personal Access Tokens provide enhanced security and can be created and managed in your account settings. They are ideal for API integrations, automated scripts, and CI/CD pipelines. Tokens can have different permissions, including:
| Name | Type | Description |
|---|---|---|
| id required | integer | The comment ID |
curl \ -H "Authorization: Bearer YOUR_API_TOKEN" \ "https://app.betahub.io/comments/123.json"
require "net/http" uri = URI("https://app.betahub.io/comments/123.json") http = Net::HTTP.new(uri.host, uri.port) http.use_ssl = true request = Net::HTTP::Get.new(uri) request["Authorization"] = "Bearer YOUR_API_TOKEN" response = http.request(request) puts response.body
import requests response = requests.get( "https://app.betahub.io/comments/123.json", headers={"Authorization": "Bearer YOUR_API_TOKEN"} ) print(response.json())
const response = await fetch("https://app.betahub.io/comments/123.json", { headers: { "Authorization": "Bearer YOUR_API_TOKEN" } }); const data = await response.json();
HttpClient client = HttpClient.newHttpClient(); HttpRequest request = HttpRequest.newBuilder() .uri(URI.create("https://app.betahub.io/comments/123.json")) .header("Authorization", "Bearer YOUR_API_TOKEN") .GET() .build(); HttpResponse<String> response = client.send( request, HttpResponse.BodyHandlers.ofString()); System.out.println(response.body());
{
"id": 0,
"body": "string",
"created_at": "2026-03-12T10:30:00Z",
"updated_at": "2026-03-12T10:30:00Z",
"solution": true,
"private_comment": true,
"user": {
"id": 0,
"name": "string",
"discord_username": "string"
},
"commentable": {
"id": 0,
"type": "string"
}
}
{
"error": "string",
"status": "string"
}
{
"error": "string",
"status": "string"
}
Authorization header for API access. Supports multiple authentication methods:
FormUser anonymous - for public operationsFormUser tkn-{token} - for authenticated operations with legacy tokensFormUser tkn-{token},email:{email} - creates/links virtual user by emailFormUser tkn-{token},discord_id:{discord_id} - creates/links virtual user by Discord IDFormUser tkn-{token},{jwt_token} - user identification with JWT token (legacy)Bearer YOUR_TOKEN_HERE - recommended for API integrationsWhen using email: or discord_id: formats with FormUser tokens, the system automatically creates or reuses virtual users. Virtual users are accounts created on-the-fly for form submissions without requiring full user registration. This is useful for:
Virtual users created this way are marked as virtual accounts and work across Issues, Feature Requests, and Support Tickets.
Validation Rules:
email: format must match RFC 5322 email format. Invalid emails will fall back to anonymous access.discord_id: format must be numeric (digits only). Invalid discord_ids will fall back to anonymous access.Personal Access Tokens provide enhanced security and can be created and managed in your account settings. They are ideal for API integrations, automated scripts, and CI/CD pipelines. Tokens can have different permissions, including:
| Name | Type | Description |
|---|---|---|
| project_id required | string |
| Name | Type | Description |
|---|---|---|
| query required | string | The search query string to match against issue titles and descriptions |
| skip_ids optional | string | Comma-separated list of issue IDs to exclude from results |
| partial optional | string |
When set to ‘true’, returns limited results optimized for autocomplete (max 4 results)
true
false
|
| scoped_id optional | string | Instead of searching, find a specific issue by its scoped ID (e.g., “123” or “g-456”) |
| Name | Type | Description |
|---|---|---|
| BetaHub-Project-ID required | string | BetaHub project ID, the same as the project_id |
curl \ -H "Authorization: Bearer YOUR_API_TOKEN" \ -H "BetaHub-Project-ID: 123" \ "https://app.betahub.io/projects/123/issues/search.json?query=example&skip_ids=123&partial=true&scoped_id=123"
require "net/http" uri = URI("https://app.betahub.io/projects/123/issues/search.json?query=example&skip_ids=123&partial=true&scoped_id=123") http = Net::HTTP.new(uri.host, uri.port) http.use_ssl = true request = Net::HTTP::Get.new(uri) request["Authorization"] = "Bearer YOUR_API_TOKEN" request["BetaHub-Project-ID"] = "123" response = http.request(request) puts response.body
import requests response = requests.get( "https://app.betahub.io/projects/123/issues/search.json?query=example&skip_ids=123&partial=true&scoped_id=123", headers={"Authorization": "Bearer YOUR_API_TOKEN", "BetaHub-Project-ID": "123"} ) print(response.json())
const response = await fetch("https://app.betahub.io/projects/123/issues/search.json?query=example&skip_ids=123&partial=true&scoped_id=123", { headers: { "Authorization": "Bearer YOUR_API_TOKEN", "BetaHub-Project-ID": "123" } }); const data = await response.json();
HttpClient client = HttpClient.newHttpClient(); HttpRequest request = HttpRequest.newBuilder() .uri(URI.create("https://app.betahub.io/projects/123/issues/search.json?query=example&skip_ids=123&partial=true&scoped_id=123")) .header("Authorization", "Bearer YOUR_API_TOKEN") .header("BetaHub-Project-ID", "123") .GET() .build(); HttpResponse<String> response = client.send( request, HttpResponse.BodyHandlers.ofString()); System.out.println(response.body());
{
"issues": [
{
"id": "1234abc",
"title": "App crashes on login screen",
"status": "open",
"priority": "high",
"created_at": "2024-10-03T12:34:56Z"
}
],
"pagination": {
"current_page": 1,
"per_page": 25,
"total_pages": 3,
"total_count": 68
},
"project_id": 123
}
{
"error": "string",
"status": "string"
}
{
"error": "string",
"status": "string"
}
Authorization header for API access. Supports multiple authentication methods:
FormUser anonymous - for public operationsFormUser tkn-{token} - for authenticated operations with legacy tokensFormUser tkn-{token},email:{email} - creates/links virtual user by emailFormUser tkn-{token},discord_id:{discord_id} - creates/links virtual user by Discord IDFormUser tkn-{token},{jwt_token} - user identification with JWT token (legacy)Bearer YOUR_TOKEN_HERE - recommended for API integrationsWhen using email: or discord_id: formats with FormUser tokens, the system automatically creates or reuses virtual users. Virtual users are accounts created on-the-fly for form submissions without requiring full user registration. This is useful for:
Virtual users created this way are marked as virtual accounts and work across Issues, Feature Requests, and Support Tickets.
Validation Rules:
email: format must match RFC 5322 email format. Invalid emails will fall back to anonymous access.discord_id: format must be numeric (digits only). Invalid discord_ids will fall back to anonymous access.Personal Access Tokens provide enhanced security and can be created and managed in your account settings. They are ideal for API integrations, automated scripts, and CI/CD pipelines. Tokens can have different permissions, including:
| Name | Type | Description |
|---|---|---|
| project_id required | string |
| Name | Type | Description |
|---|---|---|
| BetaHub-Project-ID required | string | BetaHub project ID, the same as the project_id |
curl \ -X POST \ -H "Authorization: Bearer YOUR_API_TOKEN" \ -H "BetaHub-Project-ID: 123" \ -d "query=string" \ -d "skip_ids=string" \ -d "partial=true" \ -d "scoped_id=string" \ "https://app.betahub.io/projects/123/issues/search.json"
require "net/http" require "json" uri = URI("https://app.betahub.io/projects/123/issues/search.json") http = Net::HTTP.new(uri.host, uri.port) http.use_ssl = true request = Net::HTTP::Post.new(uri) request["Authorization"] = "Bearer YOUR_API_TOKEN" request["BetaHub-Project-ID"] = "123" request.set_form_data({ "query" => "string", "skip_ids" => "string", "partial" => "true", "scoped_id" => "string" }) response = http.request(request) puts response.body
import requests response = requests.post( "https://app.betahub.io/projects/123/issues/search.json", headers={"Authorization": "Bearer YOUR_API_TOKEN", "BetaHub-Project-ID": "123"}, data={"query": "string", "skip_ids": "string", "partial": "true", "scoped_id": "string"} ) print(response.json())
const response = await fetch("https://app.betahub.io/projects/123/issues/search.json", { method: "POST", headers: { "Authorization": "Bearer YOUR_API_TOKEN", "BetaHub-Project-ID": "123" } }); const data = await response.json();
HttpClient client = HttpClient.newHttpClient(); HttpRequest request = HttpRequest.newBuilder() .uri(URI.create("https://app.betahub.io/projects/123/issues/search.json")) .header("Authorization", "Bearer YOUR_API_TOKEN") .header("BetaHub-Project-ID", "123") .header("Content-Type", "application/json") .POST(HttpRequest.BodyPublishers.ofString("{\"query\":\"string\",\"skip_ids\":\"string\",\"partial\":\"true\",\"scoped_id\":\"string\"}")) .build(); HttpResponse<String> response = client.send( request, HttpResponse.BodyHandlers.ofString()); System.out.println(response.body());
{
"query": "string",
"skip_ids": "string",
"partial": "true",
"scoped_id": "string"
}
{}
{
"error": "string",
"status": "string"
}
{
"error": "string",
"status": "string"
}