Error Reference
Every API error returns a consistent JSON structure with a machine-readable code, a
human-readable message, and a doc_url pointing back here. This page covers
every error you might encounter, why it happens, and how to fix it.
{
"success": false,
"error": {
"type": "invalid_request_error",
"code": "parameter_missing",
"message": "The 'title' field is required.",
"param": "title",
"doc_url": "https://cstar.help/developers/errors#parameter_missing",
"request_id": "req_abc123"
}
}Error Types
Every error falls into one of five top-level types. The type field tells you the
category, while code gives you the specific error.
authentication_error API key is missing, invalid, expired, or doesn't have the right permissions.
invalid_request_error The request has invalid parameters, missing fields, bad JSON, or conflicts.
not_found_error The resource you're trying to access doesn't exist.
rate_limit_error You've exceeded the rate limit for your API key type.
api_error Something went wrong on our end. These are rare and usually transient.
Authentication Errors
authentication_required 401Why this happens
- You didn't include an
Authorizationheader in your request - The header format is wrong (should be
Bearer sk_live_xxx) - You accidentally included extra whitespace or newlines in the header
How to fix it
# Correct format
curl -H "Authorization: Bearer sk_live_your_key_here" \
https://www.cstar.help/api/v1/teams/{teamId}/ticketsimport { CStarClient } from '@cstar.help/js';
const cstar = new CStarClient({ apiKey: 'sk_live_your_key_here' });
// Auth header is set automatically on every requestinvalid_api_key 401Why this happens
- The key was revoked from the dashboard or via
cstar keys revoke - You're using a key from a different team or environment
- The key was copied incorrectly (truncated or extra characters)
How to fix it
# Check your current key status
cstar status
# List all valid keys
cstar keys list
# Create a new key if needed
cstar keys create --name "My App"invalid_key_format 401Why this happens
- The key doesn't start with a recognized prefix (
sk_live_,sk_test_,pk_live_,pk_test_) - You might be passing an OAuth token or JWT instead of an API key
Valid key formats
sk_live_*Secret key — production, full accesssk_test_*Secret key — test mode, full accesspk_live_*Publishable key — production, read-onlypk_test_*Publishable key — test mode, read-onlykey_expired 401Why this happens
- The key was created with an expiration date that has passed
- Your team's security policy may auto-expire keys after a set period
How to fix it
Generate a new key from your dashboard or CLI:
cstar keys create --name 'Replacement Key'insufficient_permissions 403Why this happens
- The key was created with restricted scopes that don't include this resource
- Your team role doesn't grant access to this operation
How to fix it
Check your key's permissions in the dashboard, or create a new key with the required scopes.
publishable_key_write 403Why this happens
- You're using a
pk_live_orpk_test_key to create, update, or delete a resource - Publishable keys are designed for client-side use and only allow read operations
How to fix it
Use a secret key (sk_live_*) for write operations. Keep secret keys server-side
— never expose them in frontend code.
// Server-side only — never expose sk_ keys in the browser
const cstar = new CStarClient({ apiKey: 'sk_live_your_secret_key' });
// This works with a secret key
await cstar.tickets.create({ title: 'New ticket' });team_access_denied 403Why this happens
- The
teamIdin the URL doesn't match the team the API key belongs to - You may have multiple teams and are using a key from the wrong one
How to fix it
# Check which team your key belongs to
cstar status
# The teamId in your URL must match
# https://www.cstar.help/api/v1/teams/{THIS_TEAM_ID}/ticketsInvalid Request Errors
parameter_missing 400Why this happens
- A required field was not included in the request body
- The field name is misspelled (e.g.,
tittleinstead oftitle) - You sent the parameter as a query param instead of in the JSON body (or vice versa)
How to fix it
Check the param field in the error response — it tells you exactly which parameter
is missing.
{
"error": {
"code": "parameter_missing",
"message": "The 'title' field is required.",
"param": "title"
}
}// Before (missing title)
await cstar.tickets.create({ priority: 'high' });
// After (title included)
await cstar.tickets.create({ title: 'Help needed', priority: 'high' });parameter_invalid 400Why this happens
- A field value doesn't match the expected type (e.g., string where number expected)
- An enum field has an invalid value (e.g.,
status: "done"when valid values arenew,open,pending,resolved,closed) - A number is out of range (e.g.,
pageSize: 500when max is 100)
How to fix it
Check the param field and refer to the API reference for valid values.
// Before (invalid priority value)
await cstar.tickets.create({ title: 'Help', priority: 'super-urgent' });
// After (valid values: low, normal, high, urgent)
await cstar.tickets.create({ title: 'Help', priority: 'urgent' });invalid_json 400Why this happens
- The JSON has a syntax error (missing comma, bracket, or quote)
- You sent form-encoded data instead of JSON
- The
Content-Typeheader is missing or wrong
How to fix it
curl -X POST \
-H "Authorization: Bearer sk_live_xxx" \
-H "Content-Type: application/json" \
-d '{"title": "Help needed"}' \
https://www.cstar.help/api/v1/teams/{teamId}/ticketsUsing the SDK? You never need to worry about this — the SDK handles JSON serialization and Content-Type headers automatically.
invalid_id_format 400Why this happens
- The ID in the URL path isn't a valid UUID or prefixed ID
- You may have included extra characters or truncated the ID
Valid ID formats
# UUID format
550e8400-e29b-41d4-a716-446655440000
# Prefixed format (resource-specific)
tkt_550e8400e29b41d4a716446655440000 (tickets)
cus_7c9e667974254de0944be07fc1f90ae7 (customers)
art_a1b2c3d4e5f6789012345678abcdef00 (articles)
whk_d4e5f6789012345678abcdef00a1b2c3 (webhooks)resource_conflict 409Why this happens
- You're trying to create a resource with a unique field that already exists (e.g., duplicate email for a customer)
- A webhook with the same URL and event combination already exists
How to fix it
Use a unique value, or update the existing resource with a PATCH request instead of creating a new one.
// Instead of creating a duplicate customer:
// await cstar.customers.create({ email: 'jane@example.com' });
// Find and update the existing one:
const { data } = await cstar.customers.list({ search: 'jane@example.com' });
if (data.length > 0) {
await cstar.customers.update(data[0].id, { name: 'Jane Doe' });
}Not Found Errors
resource_not_found 404Why this happens
- The resource ID doesn't exist (it may have been deleted)
- The ID is correct but belongs to a different team
- You're using a test-mode key but the resource was created in live mode (or vice versa)
How to fix it
try {
const { data } = await cstar.tickets.get('tkt_abc123');
console.log(data);
} catch (err) {
if (err.code === 'resource_not_found') {
console.log('Ticket not found — it may have been deleted');
}
}Make sure you're using the right environment. Resources created with sk_test_ keys are only visible with test keys, and vice versa.
Rate Limit Errors
rate_limit_exceeded 429Current limits
sk_live_* / sk_test_*1,000 requests per hourpk_live_* / pk_test_*100 requests per hourRate limit headers
Every response includes these headers so you can track your usage:
X-RateLimit-LimitMax requests per windowX-RateLimit-RemainingRequests remainingX-RateLimit-ResetUnix timestamp when window resetsRetry-AfterSeconds to wait (only on 429)How to fix it
async function withRetry(fn, maxRetries = 3) {
for (let i = 0; i < maxRetries; i++) {
try {
return await fn();
} catch (err) {
if (err.code === 'rate_limit_exceeded' && i < maxRetries - 1) {
const delay = Math.pow(2, i) * 1000; // 1s, 2s, 4s
console.log(`Rate limited. Retrying in ${delay}ms...`);
await new Promise(r => setTimeout(r, delay));
} else {
throw err;
}
}
}
}Webhook deliveries do NOT count against your rate limit. You can receive unlimited webhooks without impacting your API quota.
Server Errors
internal_error 500Why this happens
- This is a bug on our side, not something you did wrong
- These are rare and usually transient
What to do
- Retry the request — most server errors are transient
- Include the
request_idfrom the error response when contacting support - If it persists, email support@cstar.help with the request ID
database_error 500What to do
- Wait a few seconds and retry — this is usually a transient issue
- If it keeps happening, the request_id will help us debug it
Handling Errors in Code
The cStar SDKs throw typed errors that you can catch and handle by code.
import { CStarClient, CStarError } from '@cstar.help/js';
const cstar = new CStarClient({ apiKey: 'sk_live_xxx' });
try {
await cstar.tickets.create({ priority: 'high' }); // missing title
} catch (err) {
if (err instanceof CStarError) {
switch (err.code) {
case 'parameter_missing':
console.log(`Missing field: ${err.param}`);
break;
case 'rate_limit_exceeded':
console.log(`Retry after ${err.retryAfter} seconds`);
break;
case 'authentication_required':
console.log('Check your API key');
break;
default:
console.log(`API error: ${err.message}`);
}
}
}