The Ark API uses conventional HTTP response codes and returns detailed error information to help you diagnose and fix issues. All SDKs provide typed exceptions for easy error handling.
All error responses follow this structure:
{
"success" : false ,
"error" : {
"code" : "validation_error" ,
"message" : "Human-readable error message" ,
"field" : "fieldName" ,
"suggestion" : "How to fix the error" ,
"hint" : "Detailed guidance with examples or documentation links"
},
"meta" : {
"requestId" : "req_abc123"
}
}
Field Description codeMachine-readable error code messageHuman-readable description fieldThe field that caused the error (if applicable) suggestionRecommended action to fix the error hintDetailed guidance with examples or documentation links (for complex errors) requestIdUnique ID for support requests
HTTP Status Codes
Status Description 200Success 201Resource created 207Partial success (batch operations) 400Bad request - invalid parameters 401Unauthorized - invalid or missing API key 403Forbidden - insufficient permissions 404Resource not found 409Conflict - resource already exists 422Unprocessable - semantic error 429Rate limit exceeded 500Server error
SDK Exception Types
All SDKs provide typed exceptions that map to HTTP status codes:
Exception HTTP Status Description BadRequestError400 Invalid request parameters AuthenticationError401 Invalid or missing API key PermissionDeniedError403 Insufficient permissions NotFoundError404 Resource not found UnprocessableEntityError422 Validation error RateLimitError429 Too many requests InternalServerError5xx Server error APIConnectionError— Network/connection issue
Handling Errors with SDKs
import ark
from ark import Ark
client = Ark()
try :
email = client.emails.send(
from_ = "hello@yourdomain.com" ,
to = [ "user@example.com" ],
subject = "Hello" ,
html = "<p>Hello!</p>"
)
print ( f "Email sent: { email.data.id } " )
except ark.BadRequestError as e:
# Invalid request parameters
print ( f "Bad request: { e.message } " )
if hasattr (e, 'code' ):
print ( f "Error code: { e.code } " )
except ark.AuthenticationError:
# Invalid or missing API key
print ( "Authentication failed - check your API key" )
except ark.RateLimitError as e:
# Too many requests - wait and retry
print ( "Rate limited - slow down requests" )
# Access retry-after header if available
# retry_after = e.response.headers.get('retry-after')
except ark.NotFoundError:
# Resource not found
print ( "Resource not found" )
except ark.APIConnectionError:
# Network error - safe to retry
print ( "Network error - retrying..." )
except ark.APIError as e:
# Catch-all for other API errors
print ( f "API error: { e.message } " )
import Ark from 'ark' ;
const client = new Ark ();
try {
const email = await client . emails . send ({
from: 'hello@yourdomain.com' ,
to: [ 'user@example.com' ],
subject: 'Hello' ,
html: '<p>Hello!</p>' ,
});
console . log ( `Email sent: ${ email . data . id } ` );
} catch ( error ) {
if ( error instanceof Ark . BadRequestError ) {
// Invalid request parameters
console . log ( `Bad request: ${ error . message } ` );
console . log ( `Error code: ${ error . code } ` );
} else if ( error instanceof Ark . AuthenticationError ) {
// Invalid or missing API key
console . log ( 'Authentication failed - check your API key' );
} else if ( error instanceof Ark . RateLimitError ) {
// Too many requests - wait and retry
console . log ( 'Rate limited - slow down requests' );
const retryAfter = error . headers ?.[ 'retry-after' ];
} else if ( error instanceof Ark . NotFoundError ) {
// Resource not found
console . log ( 'Resource not found' );
} else if ( error instanceof Ark . APIConnectionError ) {
// Network error - safe to retry
console . log ( 'Network error - retrying...' );
} else if ( error instanceof Ark . APIError ) {
// Catch-all for other API errors
console . log ( `API error: ${ error . message } ` );
}
}
require "ark_email"
client = ArkEmail :: Client . new
begin
email = client. emails . send_ (
from: "hello@yourdomain.com" ,
to: [ "user@example.com" ],
subject: "Hello" ,
html: "<p>Hello!</p>"
)
puts "Email sent: #{ email. data . id } "
rescue ArkEmail :: Errors :: BadRequestError => e
# Invalid request parameters
puts "Bad request: #{ e. message } "
puts "Error code: #{ e. code } " if e. respond_to? ( :code )
rescue ArkEmail :: Errors :: AuthenticationError
# Invalid or missing API key
puts "Authentication failed - check your API key"
rescue ArkEmail :: Errors :: RateLimitError => e
# Too many requests - wait and retry
puts "Rate limited - slow down requests"
rescue ArkEmail :: Errors :: NotFoundError
# Resource not found
puts "Resource not found"
rescue ArkEmail :: Errors :: APIConnectionError
# Network error - safe to retry
puts "Network error - retrying..."
rescue ArkEmail :: Errors :: APIError => e
# Catch-all for other API errors
puts "API error: #{ e. message } "
end
import (
" errors "
" fmt "
" github.com/ArkHQ-io/ark-go "
)
client := ark . NewClient ()
email , err := client . Emails . Send ( ctx , ark . EmailSendParams {
From : "hello@yourdomain.com" ,
To : [] string { "user@example.com" },
Subject : "Hello" ,
HTML : ark . String ( "<p>Hello!</p>" ),
})
if err != nil {
var arkErr * ark . Error
if errors . As ( err , & arkErr ) {
switch arkErr . StatusCode {
case 400 :
// Invalid request parameters
fmt . Printf ( "Bad request: %s \n " , arkErr . Message )
case 401 :
// Invalid or missing API key
fmt . Println ( "Authentication failed - check your API key" )
case 429 :
// Too many requests - wait and retry
fmt . Println ( "Rate limited - slow down requests" )
case 404 :
// Resource not found
fmt . Println ( "Resource not found" )
default :
// Other API errors
fmt . Printf ( "API error %d : %s \n " , arkErr . StatusCode , arkErr . Message )
}
} else {
// Network or other error
fmt . Printf ( "Error: %v \n " , err )
}
return
}
fmt . Printf ( "Email sent: %s \n " , email . Data . ID )
Error Codes Reference
Authentication Errors
Code Description Solution authentication_requiredNo API key provided Add Authorization: Bearer <key> header invalid_api_keyAPI key is malformed Check key format (should start with ark_) expired_api_keyAPI key has been revoked Generate a new key permission_deniedKey lacks required scope Use a key with appropriate permissions
Validation Errors
Code Description Solution validation_errorRequest failed validation Check the field and suggestion invalid_email_formatEmail address is invalid Fix the email format missing_required_fieldRequired field not provided Add the missing field invalid_field_valueField value is not allowed Check allowed values invalid_raw_messageRaw MIME message is invalid Check the hint field for detailed guidance
Resource Errors
Code Description Solution resource_not_foundResource doesn’t exist Check the ID already_existsResource already exists Use existing or choose different identifier invalid_stateOperation not allowed in current state Check resource status
Sending Errors
Code Description Solution domain_not_verifiedSending domain not verified Complete domain setup or use sandbox mode suppressed_recipientEmail is on suppression list Remove from suppressions or skip
Sandbox Errors
These errors occur when using sandbox mode (sending from @arkhq.io addresses):
Code Description Solution sandbox_recipient_not_allowedRecipient is not an organization member Add recipient to your team at arkhq.io/org/team , or set up a custom domain to send to anyone sandbox_rate_limit_exceededDaily sandbox limit (10 emails/day) reached Wait 24 hours for the limit to reset, or set up a custom domain for unlimited sending
Sandbox Mode: Sandbox is designed for testing the API without domain verification. Use sandbox@arkhq.io as the sender to send test emails to organization members. No billing charges apply to sandbox emails.
Billing Errors
Billing errors occur when your account doesn’t have an active plan or has exceeded its email limit.
Code Description Solution billing_not_configuredBilling hasn’t been set up Visit billing settings to choose a plan insufficient_balanceEmail limit reached for current plan Upgrade your plan or wait for your next billing cyclebilling_errorBilling system temporarily unavailable Retry your request; the system will fail-open if issues persist
Fail-open design: If the billing system experiences temporary issues, emails are still accepted to prevent service disruption. You’re only charged for successfully processed emails.
Handling Billing Errors in SDKs
import ark
from ark import Ark
client = Ark()
try :
email = client.emails.send(
from_ = "hello@yourdomain.com" ,
to = [ "user@example.com" ],
subject = "Hello" ,
html = "<p>Hello!</p>"
)
except ark.BadRequestError as e:
if e.code == "insufficient_balance" :
print ( "Upgrade your plan at https://arkhq.io/org/billing" )
elif e.code == "billing_not_configured" :
print ( "Set up billing at https://arkhq.io/org/billing" )
import Ark from 'ark-email' ;
const client = new Ark ();
try {
const email = await client . emails . send ({
from: 'hello@yourdomain.com' ,
to: [ 'user@example.com' ],
subject: 'Hello' ,
html: '<p>Hello!</p>' ,
});
} catch ( error ) {
if ( error instanceof Ark . BadRequestError ) {
if ( error . code === 'insufficient_balance' ) {
console . log ( 'Upgrade your plan at https://arkhq.io/org/billing' );
} else if ( error . code === 'billing_not_configured' ) {
console . log ( 'Set up billing at https://arkhq.io/org/billing' );
}
}
}
Automatic Retries
All SDKs automatically retry failed requests with exponential backoff for:
Connection errors
408 Request Timeout
409 Conflict
429 Rate Limit
5xx Server Errors
Default: 2 retries. Configure per-client:
client = Ark( max_retries = 5 ) # 5 retries
client = Ark( max_retries = 0 ) # Disable retries
const client = new Ark ({ maxRetries: 5 }); // 5 retries
const client = new Ark ({ maxRetries: 0 }); // Disable retries
client = ArkEmail :: Client . new ( max_retries: 5 ) # 5 retries
client = ArkEmail :: Client . new ( max_retries: 0 ) # Disable retries
client := ark . NewClient ( option . WithMaxRetries ( 5 )) // 5 retries
client := ark . NewClient ( option . WithMaxRetries ( 0 )) // Disable retries
Getting Help
If you encounter persistent errors:
Check the requestId in the error response
Review your request parameters
Check the status page for outages
Contact support with the requestId
API Reference View complete API documentation
SDK Documentation Learn more about SDK error handling