Skip to main content

Error Response Format

When an API request fails, the response includes a structured error with a machine-readable code and human-readable detail:
{
  "detail": {
    "detail": "You are not the author of 'my-skill'",
    "code": "SKILL_NOT_OWNER"
  }
}
The HTTP status code indicates the error category. The code field enables precise error handling in your application.

Authentication Errors

CodeHTTP StatusDescription
AUTH_MISSING401No Authorization header provided. Include a Bearer token.
AUTH_INVALID401The provided token is invalid or malformed.
AUTH_EXPIRED401The token has expired. Sign in again to get a fresh token.

Skill Errors

CodeHTTP StatusDescription
SKILL_NOT_FOUND404The requested skill slug does not exist.
SKILL_BLOCKED403The skill was blocked by the security review pipeline.
SKILL_SLUG_TAKEN409The slug is already in use. Choose a different name.
SKILL_NOT_OWNER403You attempted to modify a skill you do not own.
SKILL_ARCHIVED400The skill has been unpublished. Use POST /v1/skills/{slug}/republish to restore it.
SKILL_VERSION_PENDING409A new version is already pending security review. Wait for it to complete.
USERNAME_REQUIRED400You must set a username before publishing. Update your profile first via PATCH /v1/users/profile.

Purchase Errors

CodeHTTP StatusDescription
PURCHASE_NOT_FOUND404No purchase found for the given ID or session.
PURCHASE_REQUIRED403You need to purchase this paid skill before downloading.
PURCHASE_DUPLICATE409You already own this skill.
PURCHASE_FREE_SKILL400This skill is free and does not require a checkout.

Claim Errors

CodeHTTP StatusDescription
CLAIM_NOT_FOUND404The claim ID does not exist or does not belong to you.
CLAIM_NOT_CLAWHUB400Only external (ClawHub) skills can be claimed.
CLAIM_ALREADY_CLAIMED409This skill has already been claimed by another user.
CLAIM_NOT_SANDBOX400The claim is not in sandbox status and cannot be approved.

License Errors

CodeHTTP StatusDescription
LICENSE_INVALID400The license code does not match any purchase.
LICENSE_REDEEMED409This license code has already been redeemed.

User Profile Errors

CodeHTTP StatusDescription
USERNAME_TAKEN409The requested username is already in use. Choose another.
VALIDATION_ERROR422Input validation failed. Check the error detail for specifics.

General Errors

CodeHTTP StatusDescription
NOT_FOUND404The requested resource was not found.
FORBIDDEN403You do not have permission to perform this action.
FILE_TOO_LARGE413The uploaded file exceeds the size limit.
STORAGE_ERROR502File storage operation failed. Retry the request.
RATE_LIMITED429Too many requests. See Rate Limits for details.

Handling Errors

Python

import httpx

response = httpx.post(f"{API_URL}/v1/checkout", json={"skill_slug": "my-skill"}, headers=headers)

if response.status_code != 200:
    error = response.json()
    code = error.get("detail", {}).get("code")
    message = error.get("detail", {}).get("detail")

    if code == "PURCHASE_DUPLICATE":
        print("You already own this skill!")
    else:
        print(f"Error: {message}")

JavaScript

const res = await fetch(`${API_URL}/v1/checkout`, {
  method: "POST",
  headers: { "Content-Type": "application/json", Authorization: `Bearer ${token}` },
  body: JSON.stringify({ skill_slug: "my-skill" }),
});

if (!res.ok) {
  const error = await res.json();
  const code = error.detail?.code;

  if (code === "PURCHASE_DUPLICATE") {
    console.log("You already own this skill!");
  } else {
    console.log(`Error: ${error.detail?.detail}`);
  }
}