Docs
Docs/API Reference/Errors

Error Codes

API error responses and how to handle them

Error Codes

When a request fails, the Octopost API returns a JSON error response with a consistent structure.

Error Response Format

{
  "error": "Human-readable error message",
  "code": "machine_readable_code",
  "details": {}
}
FieldTypeDescription
errorstringA human-readable description of what went wrong.
codestringA machine-readable error code for programmatic handling.
detailsobject | undefinedAdditional context about the error. Present on validation errors and some other error types.

Error Codes Reference

400 Bad Request

{
  "error": "Request body must be valid JSON",
  "code": "bad_request"
}

The request was malformed. Common causes:

  • Invalid JSON in the request body.
  • Missing Content-Type: application/json header.
  • Unsupported HTTP method for the endpoint.

401 Unauthorized

{
  "error": "Invalid or expired API key",
  "code": "unauthorized"
}

Authentication failed. Common causes:

  • Missing Authorization header.
  • Malformed header (must be Bearer <key>).
  • API key has been revoked.
  • Using a test key against a live-only endpoint.

403 Forbidden

{
  "error": "API key does not have permission for this action",
  "code": "forbidden"
}

The API key is valid but lacks the required permission. Common causes:

  • Key is scoped to posts:read but the request is a write operation.
  • Attempting to modify a system preset.
  • Attempting to access another user's resource.

404 Not Found

{
  "error": "Post not found",
  "code": "not_found"
}

The requested resource does not exist. Common causes:

  • Invalid resource ID.
  • Resource was deleted.
  • Resource belongs to a different user.

409 Conflict

{
  "error": "Post has already been published and cannot be modified",
  "code": "conflict"
}

The request conflicts with the current state of the resource. Common causes:

  • Attempting to update a published post.
  • Attempting to publish a post that is already publishing.
  • Attempting to set a default preset when the operation would create an invalid state.

422 Validation Error

{
  "error": "Validation failed",
  "code": "validation_error",
  "details": {
    "fields": {
      "content": "Content is required",
      "platforms": "At least one platform must be specified"
    }
  }
}

The request body is valid JSON but contains invalid data. The details.fields object maps field names to their specific validation errors.

Common causes:

  • Missing required fields.
  • Content exceeds a platform's character limit.
  • Invalid platform identifier.
  • scheduled_for is in the past.
  • primary_platform is not included in platforms array.
  • No connected account found for a specified platform.

429 Rate Limited

{
  "error": "Rate limit exceeded. Try again in 45 seconds.",
  "code": "rate_limited",
  "details": {
    "limit": 300,
    "remaining": 0,
    "reset_at": "2026-04-03T12:01:00Z",
    "retry_after": 45
  }
}

Too many requests. See the Rate Limits guide for backoff strategies.


500 Server Error

{
  "error": "An unexpected error occurred. Please try again later.",
  "code": "server_error"
}

Something went wrong on our end. These errors are automatically logged and investigated. If the problem persists, contact support.


Retryable vs Non-Retryable Errors

When building resilient integrations, distinguish between errors that are safe to retry and those that require user intervention.

Retryable

These errors are transient. Retry after a delay.

CodeHTTP StatusRetry Strategy
rate_limited429Wait for Retry-After header or details.retry_after seconds.
server_error500Retry with exponential backoff (1s, 2s, 4s, 8s). Maximum 5 retries.
-502Retry with exponential backoff.
-503Retry with exponential backoff.
-504Retry with exponential backoff.

Non-Retryable

These errors require a fix before retrying.

CodeHTTP StatusAction Required
bad_request400Fix the request format or parameters.
unauthorized401Check or regenerate the API key.
forbidden403Use a key with the correct permissions.
not_found404Verify the resource ID exists.
conflict409Check the resource's current state before retrying the operation.
validation_error422Fix the request body based on details.fields.

Example: Error Handling in TypeScript

interface OctopostError {
  error: string;
  code: string;
  details?: Record<string, unknown>;
}

async function createPost(content: string, platforms: string[]) {
  const response = await fetch("https://api.octopost.ink/v1/posts", {
    method: "POST",
    headers: {
      Authorization: `Bearer ${process.env.OCTOPOST_API_KEY}`,
      "Content-Type": "application/json",
    },
    body: JSON.stringify({ content, platforms }),
  });

  if (!response.ok) {
    const error: OctopostError = await response.json();

    switch (error.code) {
      case "unauthorized":
        throw new Error("API key is invalid. Check your configuration.");
      case "validation_error":
        console.error("Validation errors:", error.details);
        throw new Error(`Validation failed: ${error.error}`);
      case "rate_limited":
        const retryAfter = (error.details as any)?.retry_after ?? 60;
        console.log(`Rate limited. Retrying in ${retryAfter}s...`);
        await new Promise((r) => setTimeout(r, retryAfter * 1000));
        return createPost(content, platforms); // retry
      case "server_error":
        throw new Error("Octopost server error. Try again later.");
      default:
        throw new Error(`API error: ${error.error}`);
    }
  }

  return response.json();
}