The shortkit API uses conventional HTTP response codes and returns structured error responses to help you handle failures gracefully.
HTTP status codes
Code Meaning 200Success 201Created - Resource successfully created 204No Content - Success with no response body 400Bad Request - Invalid request parameters 401Unauthorized - Invalid or missing API key 403Forbidden - Key lacks required permissions 404Not Found - Resource doesn’t exist 409Conflict - Resource state conflict 422Unprocessable Entity - Validation failed 429Too Many Requests - Rate limit exceeded 500Internal Server Error - Server-side issue 503Service Unavailable - Temporary outage
All errors follow a consistent structure:
{
"error" : {
"code" : "VALIDATION_ERROR" ,
"message" : "Title is required" ,
"details" : {
"field" : "title" ,
"reason" : "required"
}
},
"meta" : {
"requestId" : "req_xyz789"
}
}
Error fields
Machine-readable error code for programmatic handling.
Human-readable error description.
Additional context about the error. Structure varies by error type.
Unique request identifier for support inquiries.
Error codes reference
Authentication errors
Code HTTP Status Description UNAUTHORIZED401 Missing or invalid API key KEY_REVOKED401 API key has been revoked KEY_EXPIRED401 API key has expired FORBIDDEN403 Insufficient permissions ENVIRONMENT_MISMATCH403 Wrong environment key
Validation errors
Code HTTP Status Description VALIDATION_ERROR400 Request validation failed INVALID_REQUEST400 Malformed request body MISSING_PARAMETER400 Required parameter missing INVALID_PARAMETER400 Parameter value invalid
Resource errors
Code HTTP Status Description NOT_FOUND404 Resource doesn’t exist ALREADY_EXISTS409 Resource already exists CONFLICT409 Resource state conflict GONE410 Resource has been deleted
Content errors
Code HTTP Status Description CONTENT_NOT_READY409 Content still processing CONTENT_FAILED422 Content processing failed INVALID_MEDIA_TYPE422 Unsupported file format FILE_TOO_LARGE422 File exceeds size limit DURATION_EXCEEDED422 Video exceeds max duration
Rate limiting errors
Code HTTP Status Description RATE_LIMITED429 Too many requests QUOTA_EXCEEDED429 Monthly quota exceeded
Server errors
Code HTTP Status Description INTERNAL_ERROR500 Unexpected server error SERVICE_UNAVAILABLE503 Temporary service outage UPSTREAM_ERROR502 Third-party service failure
Handling errors
Basic error handling
async function createContent ( data ) {
try {
const response = await fetch ( 'https://api.shortkit.dev/v1/content' , {
method : 'POST' ,
headers : {
'Authorization' : `Bearer ${ apiKey } ` ,
'Content-Type' : 'application/json'
},
body : JSON . stringify ( data )
});
if ( ! response . ok ) {
const error = await response . json ();
throw new ShortkitError ( error );
}
return response . json ();
} catch ( error ) {
handleError ( error );
}
}
function handleError ( error ) {
switch ( error . code ) {
case 'VALIDATION_ERROR' :
console . error ( `Validation failed: ${ error . message } ` );
break ;
case 'RATE_LIMITED' :
// Implement retry with backoff
break ;
case 'UNAUTHORIZED' :
// Refresh credentials or redirect to login
break ;
default :
console . error ( `API error: ${ error . message } ` );
}
}
import requests
from requests.exceptions import RequestException
def create_content ( data ):
try :
response = requests. post (
'https://api.shortkit.dev/v1/content' ,
headers = {
'Authorization' : f 'Bearer { api_key } ' ,
'Content-Type' : 'application/json'
},
json = data
)
response. raise_for_status ()
return response. json ()
except requests.HTTPError as e:
error = e.response. json ()
handle_error (error[ 'error' ])
def handle_error ( error ):
code = error. get ( 'code' )
message = error. get ( 'message' )
if code == 'VALIDATION_ERROR' :
print ( f "Validation failed: { message } " )
elif code == 'RATE_LIMITED' :
# Implement retry with backoff
pass
elif code == 'UNAUTHORIZED' :
# Refresh credentials
pass
else :
print ( f "API error: { message } " )
func createContent ( data ContentRequest ) ( * Content , error ) {
resp , err := client . Post (
"https://api.shortkit.dev/v1/content" ,
data ,
)
if err != nil {
return nil , err
}
if resp . StatusCode >= 400 {
var apiErr APIError
json . NewDecoder ( resp . Body ). Decode ( & apiErr )
return nil , handleError ( apiErr )
}
var content Content
json . NewDecoder ( resp . Body ). Decode ( & content )
return & content , nil
}
func handleError ( err APIError ) error {
switch err . Error . Code {
case "VALIDATION_ERROR" :
return fmt . Errorf ( "validation failed: %s " , err . Error . Message )
case "RATE_LIMITED" :
// Implement retry with backoff
return ErrRateLimited
case "UNAUTHORIZED" :
return ErrUnauthorized
default :
return fmt . Errorf ( "API error: %s " , err . Error . Message )
}
}
Retry with exponential backoff
For transient errors (429, 503), implement retry logic:
async function fetchWithRetry ( url , options , maxRetries = 3 ) {
for ( let attempt = 0 ; attempt <= maxRetries ; attempt ++ ) {
try {
const response = await fetch ( url , options );
if ( response . status === 429 || response . status === 503 ) {
if ( attempt === maxRetries ) throw new Error ( 'Max retries exceeded' );
// Get retry delay from header or use exponential backoff
const retryAfter = response . headers . get ( 'Retry-After' );
const delay = retryAfter
? parseInt ( retryAfter ) * 1000
: Math . pow ( 2 , attempt ) * 1000 ;
await sleep ( delay );
continue ;
}
return response ;
} catch ( error ) {
if ( attempt === maxRetries ) throw error ;
await sleep ( Math . pow ( 2 , attempt ) * 1000 );
}
}
}
function sleep ( ms ) {
return new Promise ( resolve => setTimeout ( resolve , ms ));
}
Validation error details
Validation errors include field-level details:
{
"error" : {
"code" : "VALIDATION_ERROR" ,
"message" : "Request validation failed" ,
"details" : {
"errors" : [
{
"field" : "title" ,
"reason" : "required" ,
"message" : "Title is required"
},
{
"field" : "duration" ,
"reason" : "max" ,
"message" : "Duration cannot exceed 180 seconds" ,
"max" : 180
}
]
}
}
}
Handle multiple validation errors:
function displayValidationErrors ( error ) {
if ( error . code !== 'VALIDATION_ERROR' ) return ;
const errors = error . details ?. errors || [];
errors . forEach ( err => {
const field = document . querySelector ( `[name=" ${ err . field } "]` );
if ( field ) {
field . classList . add ( 'error' );
showFieldError ( field , err . message );
}
});
}
SDK error handling
The SDKs provide typed error classes:
shortKit. fetchFeed { result in
switch result {
case . success ( let feed) :
self . displayFeed (feed)
case . failure ( let error) :
switch error {
case . networkError ( let underlying) :
self . showNetworkError ()
case . authenticationError :
self . refreshCredentials ()
case . rateLimited ( let retryAfter) :
self . scheduleRetry ( after : retryAfter)
case . serverError ( let code, let message) :
self . showError (message)
}
}
}
shortKit. fetchFeed (
onSuccess = { feed ->
displayFeed (feed)
},
onError = { error ->
when (error) {
is ShortkitError.NetworkError -> showNetworkError ()
is ShortkitError.AuthenticationError -> refreshCredentials ()
is ShortkitError.RateLimited -> scheduleRetry (error.retryAfter)
is ShortkitError.ServerError -> showError (error.message)
}
}
)
try {
const feed = await shortkit . fetchFeed ();
displayFeed ( feed );
} catch ( error ) {
if ( error instanceof ShortkitError ) {
switch ( error . code ) {
case 'NETWORK_ERROR' :
showNetworkError ();
break ;
case 'UNAUTHORIZED' :
refreshCredentials ();
break ;
case 'RATE_LIMITED' :
scheduleRetry ( error . retryAfter );
break ;
default :
showError ( error . message );
}
}
}
Debugging errors
Using request IDs
Every response includes a requestId. Include this when contacting support:
curl -i https://api.shortkit.dev/v1/content/cnt_abc123 \
-H "Authorization: Bearer sk_live_..."
# Response headers include:
# X-Request-Id: req_xyz789
Verbose logging
Enable verbose logging in SDKs for debugging:
shortkit . setLogLevel ( 'verbose' );
Common issues
401 Unauthorized with valid key
Check for extra whitespace in the key
Verify key hasn’t been revoked
Confirm environment matches (live vs test)
Ensure domain is in your allowlist
Check that you’re using a publishable key
Verify request origin matches configuration
Check shortkit status page
Implement retry logic
Contact support with request IDs
Validation errors on previously working requests
Check for API version changes
Review changelog for breaking changes
Verify request body structure
Next steps