Errors
The TokPortal API uses a consistent error format across all endpoints. Errors are returned as JSON with an error object.
Error Response Format
{
"error": {
"code": "ERROR_CODE",
"message": "A human-readable description of the problem.",
"details": {}
}
}
| Field | Type | Description |
|---|---|---|
code | string | Machine-readable error code. Use this for programmatic handling. |
message | string | Human-readable description. May change — do not match against this. |
details | object | Optional. Additional context (e.g., which field failed validation, credit breakdown). |
Error Code Reference
Authentication Errors
| Code | HTTP | Description |
|---|---|---|
AUTH_MISSING_KEY | 401 | No X-API-Key header was provided in the request. |
AUTH_INVALID_KEY | 401 | The API key does not match any account. |
AUTH_REVOKED_KEY | 401 | The API key has been revoked. Generate a new key from the developer dashboard. |
Rate Limiting
| Code | HTTP | Description |
|---|---|---|
RATE_LIMIT_EXCEEDED | 429 | Too many requests. Wait and retry. See Rate Limits. |
Billing
| Code | HTTP | Description |
|---|---|---|
INSUFFICIENT_CREDITS | 402 | Not enough credits. Response includes required, available, missing, and breakdown in details. |
Bundle Errors
| Code | HTTP | Description |
|---|---|---|
BUNDLE_NOT_FOUND | 404 | The specified bundle does not exist. |
BUNDLE_NOT_OWNED | 403 | The bundle belongs to another account. |
BUNDLE_INVALID_STATUS | 409 | The bundle is not in a valid status for this operation (e.g., trying to configure a published bundle). |
BUNDLE_ALREADY_PUBLISHED | 409 | The bundle has already been published and cannot be modified. |
Account Errors
| Code | HTTP | Description |
|---|---|---|
ACCOUNT_NOT_FOUND | 404 | The specified account does not exist. |
ACCOUNT_INVALID_STATUS | 409 | The account is not in a valid status for this operation. |
ACCOUNT_NOT_CONFIGURED | 409 | The account must be configured before this operation can proceed. |
Saved Account Errors
| Code | HTTP | Description |
|---|---|---|
SAVED_ACCOUNT_NOT_FOUND | 404 | The specified saved account does not exist. |
SAVED_ACCOUNT_NOT_OWNED | 403 | The saved account belongs to another user. |
Video Errors
| Code | HTTP | Description |
|---|---|---|
VIDEO_NOT_FOUND | 404 | The specified video does not exist. |
VIDEO_INVALID_STATUS | 409 | The video is not in a valid status for this operation. |
VIDEO_POSITION_OUT_OF_RANGE | 400 | The video position exceeds the available slots. |
Validation Errors
| Code | HTTP | Description |
|---|---|---|
INVALID_COUNTRY | 400 | The country code is not supported. |
INVALID_PLATFORM | 400 | The platform is not supported. Valid values: tiktok, instagram, youtube. |
INVALID_VIDEO_TYPE | 400 | The video type is not valid for the target platform. |
INVALID_DATE | 400 | The date is malformed or out of the allowed range. |
INVALID_FIELD | 400 | A field value is invalid (details specify which field and why). |
INVALID_BODY | 400 | The request body is malformed or not valid JSON. |
MISSING_FIELD | 400 | A required field is missing from the request body. |
Configuration Errors
| Code | HTTP | Description |
|---|---|---|
EDIT_SLOTS_EXCEEDED | 400 | The number of edit slots exceeds the allowed limit. |
WARMING_CONFLICT | 400 | Conflicting warming options were specified. |
DEEP_WARMING_PLATFORM | 400 | Deep warming is only available for Instagram accounts. |
VIDEOS_ONLY_REQUIRES_ACCOUNT | 400 | A videos-only bundle requires an existing saved account. |
Analytics Errors
| Code | HTTP | Description |
|---|---|---|
ANALYTICS_COOLDOWN | 429 | Analytics were recently refreshed. Wait before requesting again. |
ANALYTICS_QUOTA_EXCEEDED | 429 | Analytics refresh quota has been exceeded for this period. |
ANALYTICS_NOT_FOUND | 404 | No analytics data is available for this account. |
Verification Errors
| Code | HTTP | Description |
|---|---|---|
VERIFICATION_CODE_NOT_FOUND | 404 | No pending verification code was found for this account. |
CSV Errors
| Code | HTTP | Description |
|---|---|---|
CSV_PARSE_ERROR | 400 | The CSV file could not be parsed. Check formatting and encoding. |
CSV_VALIDATION_ERROR | 400 | The CSV content failed validation. details includes row-level errors. |
Server Errors
| Code | HTTP | Description |
|---|---|---|
UPLOAD_FAILED | 500 | A file upload failed. Retry the request. |
INTERNAL_ERROR | 500 | An unexpected server error occurred. If this persists, contact support. |
Handling Errors in Code
const response = await fetch("https://app.tokportal.com/api/ext/bundles", {
method: "POST",
headers: {
"X-API-Key": process.env.TOKPORTAL_API_KEY,
"Content-Type": "application/json",
},
body: JSON.stringify(bundleConfig),
});
const result = await response.json();
if (result.error) {
switch (result.error.code) {
case "INSUFFICIENT_CREDITS":
console.error(
`Need ${result.error.details.missing} more credits.`
);
break;
case "AUTH_INVALID_KEY":
console.error("Invalid API key. Check your configuration.");
break;
case "RATE_LIMIT_EXCEEDED":
// Wait and retry
await new Promise((r) => setTimeout(r, 5000));
break;
default:
console.error(`API error: ${result.error.message}`);
}
}