Skip to main content

Error Handling

The Soku API uses standard HTTP status codes and returns structured error responses with machine-readable codes, human-readable messages, and request identifiers for troubleshooting.

Error Response Format

All error responses follow a consistent JSON structure:
{
  "error": {
    "type": "invalid_request_error",
    "code": "error_code_here",
    "message": "A human-readable description of the error.",
    "timestamp": "2026-02-28T12:00:00.000Z",
    "requestId": "req_abc123def456",
    "details": {}
  }
}
FieldTypeDescription
error.typestringThe error category: "invalid_request_error" (4xx), "authentication_error" (401/403), or "api_error" (5xx)
error.codestringA machine-readable error code. Use this for programmatic error handling.
error.messagestringA human-readable description of the error. Suitable for logging but not guaranteed to be stable across API versions.
error.timestampstringISO 8601 timestamp of when the error occurred
error.requestIdstringA unique identifier for the request. Include this when contacting support.
error.detailsobjectAdditional context about the error. The shape varies by error type. May be empty or omitted.

Error Codes Reference

400 Bad Request

validation_error

One or more fields in the request body are missing, malformed, or contain invalid values.
{
  "error": {
    "code": "validation_error",
    "message": "The 'text' field is required when mediaType is 'text'.",
    "timestamp": "2026-02-28T12:00:00.000Z",
    "requestId": "req_abc123def456",
    "details": {
      "field": "post.content.text",
      "reason": "required"
    }
  }
}
Common causes and solutions:
CauseSolution
Missing required fieldCheck the endpoint documentation for required fields
Invalid field type (for example, string instead of array)Verify the data types match the API specification
Invalid URL format in media fieldsEnsure URLs are well-formed with http:// or https://
Empty platform arrayInclude at least one platform target
Invalid scheduledTime formatUse ISO 8601 format: 2026-03-02T09:00:00.000Z
scheduledTime is in the pastUse a future timestamp

upload_failed

The media URL provided in the request could not be downloaded or stored.
{
  "error": {
    "type": "invalid_request_error",
    "code": "upload_failed",
    "message": "Media URL could not be downloaded or stored.",
    "timestamp": "2026-02-28T12:00:00.000Z",
    "requestId": "req_abc123def456"
  }
}
Common causes and solutions:
CauseSolution
Media URL is unreachable or returns an errorVerify the URL is publicly accessible
Media file is too largeCheck platform-specific size limits
Unsupported media formatUse a supported format (MP4, JPEG, PNG, WebP)

missing_integrations

One or more platform targets in the request are not connected to your Soku account.
{
  "error": {
    "code": "missing_integrations",
    "message": "The following platforms are not connected: tiktok, youtube. Connect them in Settings > Integrations.",
    "timestamp": "2026-02-28T12:00:00.000Z",
    "requestId": "req_abc123def456",
    "details": {
      "missingPlatforms": ["tiktok", "youtube"]
    }
  }
}
Solution: Connect the missing platforms in the Soku dashboard under Settings > Integrations before making API calls that target them.

missing_account

The specified accountId does not exist for the given platform, or you have multiple accounts for a platform and did not specify which one to use.
{
  "error": {
    "code": "missing_account",
    "message": "No account found with ID 'ig_nonexistent' for platform 'instagram'.",
    "timestamp": "2026-02-28T12:00:00.000Z",
    "requestId": "req_abc123def456",
    "details": {
      "platform": "instagram",
      "accountId": "ig_nonexistent"
    }
  }
}
Common causes and solutions:
CauseSolution
Typo in accountIdVerify the account ID in Settings > Integrations
Account was disconnectedReconnect the account in the dashboard
Multiple accounts exist but no accountId specifiedUse the object format with platform and accountId instead of a string

401 Unauthorized

unauthorized

The request is missing authentication credentials, or the provided credentials are invalid.
{
  "error": {
    "code": "unauthorized",
    "message": "Invalid or missing API key.",
    "timestamp": "2026-02-28T12:00:00.000Z",
    "requestId": "req_abc123def456"
  }
}
Common causes and solutions:
CauseSolution
soku-api-key header is missingAdd the header to your request
API key is misspelled or truncatedVerify you copied the full key including the sk_live_ prefix
API key has been revokedCreate a new key in Settings > API Keys
Using Authorization instead of soku-api-keyUse the correct header name: soku-api-key
Firebase ID token is invalid (key management endpoints)Refresh your Firebase ID token

402 Payment Required

insufficient_credits

Your account does not have enough AI credits to complete the requested operation.
{
  "error": {
    "code": "insufficient_credits",
    "message": "Your account does not have enough AI credits to complete this transcription. Estimated cost: 15 credits. Current balance: 3 credits.",
    "timestamp": "2026-02-28T12:00:00.000Z",
    "requestId": "req_abc123def456",
    "details": {
      "estimatedCost": 15,
      "currentBalance": 3
    }
  }
}
Solution: Purchase additional AI credits in the Soku dashboard under Account > Credits. See Credits System for pricing details.

403 Forbidden

forbidden

The request was authenticated but the account does not have permission to perform the action. This typically means your subscription is not active.
{
  "error": {
    "code": "forbidden",
    "message": "An active subscription is required to access the API.",
    "timestamp": "2026-02-28T12:00:00.000Z",
    "requestId": "req_abc123def456"
  }
}
Common causes and solutions:
CauseSolution
Subscription has expiredRenew your subscription in Account > Billing
Subscription was canceledResubscribe from the billing page
Free trial has endedSubscribe to a paid plan
Payment method declinedUpdate your payment method in Account > Billing

404 Not Found

not_found

The requested resource does not exist.
{
  "error": {
    "code": "not_found",
    "message": "No template found with slug 'nonExistentTemplate'.",
    "timestamp": "2026-02-28T12:00:00.000Z",
    "requestId": "req_abc123def456"
  }
}
Common causes and solutions:
CauseSolution
Invalid template slugCheck your template slugs in the Templates section of the dashboard
Invalid media IDVerify the media ID exists in your media library
Invalid repurpose link IDList your repurpose links with GET /v1/repurposeLinks to find valid IDs
Invalid API key ID (for revocation)List your keys with GET /v1/api-keys to find valid IDs

409 Conflict

idempotency_conflict

The same idempotency key was used with a different request payload.
{
  "error": {
    "type": "invalid_request_error",
    "code": "idempotency_conflict",
    "message": "The provided idempotency key was already used with a different request body.",
    "timestamp": "2026-02-28T12:00:00.000Z",
    "requestId": "req_abc123def456"
  }
}
Solution: Use a new, unique idempotency key for each distinct request payload. If you are retrying the same request, reuse the same key with the same body.

429 Too Many Requests

rate_limit_exceeded

You have exceeded the rate limit for your tier.
{
  "error": {
    "code": "rate_limit_exceeded",
    "message": "Rate limit exceeded. Please retry after 12 seconds.",
    "timestamp": "2026-02-28T12:00:00.000Z",
    "requestId": "req_abc123def456",
    "details": {
      "retryAfter": 12,
      "limit": 100,
      "tier": "premium"
    }
  }
}
The response also includes a Retry-After header with the number of seconds to wait. Solution: Wait the number of seconds specified in the Retry-After header before retrying. Implement exponential backoff in your client. See Rate Limits for best practices.

500 Internal Server Error

dispatch_failed

The post was created but delivery to one or more platforms failed during dispatching.
{
  "error": {
    "code": "dispatch_failed",
    "message": "Post was created but failed to dispatch to one or more platforms.",
    "timestamp": "2026-02-28T12:00:00.000Z",
    "requestId": "req_abc123def456",
    "details": {
      "failedPlatforms": ["tiktok"],
      "succeededPlatforms": ["instagram", "threads"]
    }
  }
}
Solution: This is typically a transient error caused by a platform API issue. Retry the request for the failed platforms. If the error persists, check the platform’s status page or reconnect the integration in the Soku dashboard.

post_creation_failed

An internal error occurred while creating the post.
{
  "error": {
    "code": "post_creation_failed",
    "message": "An internal error occurred while creating the post. Please try again.",
    "timestamp": "2026-02-28T12:00:00.000Z",
    "requestId": "req_abc123def456"
  }
}
Solution: Retry the request. If the error persists, contact support with the requestId.

internal_error

A general internal server error.
{
  "error": {
    "code": "internal_error",
    "message": "An unexpected error occurred. Please try again later.",
    "timestamp": "2026-02-28T12:00:00.000Z",
    "requestId": "req_abc123def456"
  }
}
Solution: Retry the request with exponential backoff. If the error persists, contact support with the requestId.

HTTP Status Code Summary

Status CodeMeaningTypical Error Codes
400Bad Requestvalidation_error, missing_integrations, missing_account, upload_failed
401Unauthorizedunauthorized
402Payment Requiredinsufficient_credits
403Forbiddenforbidden
404Not Foundnot_found
409Conflictidempotency_conflict
429Too Many Requestsrate_limit_exceeded
500Internal Server Errordispatch_failed, post_creation_failed, internal_error

Error Handling Best Practices

Use the error code, not the message

Always base your error handling logic on the error.code field, not error.message. Messages may change between API versions; codes are stable.
// Correct: switch on error code
if (error.code === 'rate_limit_exceeded') {
  await waitAndRetry();
} else if (error.code === 'insufficient_credits') {
  notifyUser('Please purchase more credits.');
}

// Incorrect: match on error message
if (error.message.includes('rate limit')) { /* fragile */ }

Log the requestId

Always log the requestId from error responses. This value is essential for debugging with Soku support.
if (!response.ok) {
  const body = await response.json();
  console.error(`API error: ${body.error.code} - ${body.error.message} (requestId: ${body.error.requestId})`);
}

Implement retry logic for transient errors

Errors with status codes 429 and 500 are often transient and can be resolved by retrying:
StatusRetry?Strategy
400NoFix the request. Retrying with the same payload will produce the same error.
401NoFix authentication. Retrying will not help.
402NoPurchase credits first.
403NoActivate subscription first.
404NoFix the resource identifier.
429YesWait for Retry-After seconds, then retry with exponential backoff.
500YesRetry with exponential backoff. Maximum 3 retries recommended.

Validate before sending

Check required fields and data formats on the client side before making an API call. This reduces unnecessary requests and avoids hitting rate limits with invalid payloads.

Getting Help

If you encounter persistent errors or need assistance debugging an issue:
  1. Note the requestId from the error response.
  2. Note the timestamp and the endpoint you called.
  3. Contact Soku support with these details for faster resolution.

Next Steps

TopicDescription
Rate LimitsDetailed rate limiting information and best practices
Code ExamplesComplete examples with error handling built in
API TroubleshootingCommon API issues and solutions