All errors follow a consistent format:
{
"error": {
"code": "error_code",
"message": "Human-readable error message",
"details": {
"additional": "context"
}
}
}
HTTP Status Codes
Success - Request completed successfully
Bad Request - Invalid request or business logic error
Unauthorized - Missing or invalid API key
Forbidden - API key doesn’t have required permissions
Not Found - Resource doesn’t exist
Conflict - Resource conflict (e.g., duplicate operation)
Validation Error - Request data failed validation
Rate Limited - Too many requests
Internal Error - Something went wrong on our end
Upstream Error - Error from upstream provider (1Shot)
Timeout - Request took too long
Error Codes
Client Errors (4xx)
Status: 400Request data is malformed or invalid.{
"error": {
"code": "invalid_request",
"message": "Transaction hash must start with 0x",
"details": {
"field": "transaction_hash"
}
}
}
Status: 401Missing or invalid API key.{
"error": {
"code": "unauthorized",
"message": "Invalid API key"
}
}
Status: 404Requested resource doesn’t exist.{
"error": {
"code": "not_found",
"message": "Verification not found: ver_invalid123"
}
}
Status: 409Resource conflict or duplicate operation.{
"error": {
"code": "conflict",
"message": "Settlement already initiated for this verification"
}
}
Status: 429Rate limit exceeded.{
"error": {
"code": "rate_limited",
"message": "Rate limit exceeded. Max 100 requests per minute."
}
}
Retry-After header indicates when to retry.
Status: 422Idempotency key reused with different request data.{
"error": {
"code": "idempotency_mismatch",
"message": "Idempotency key already used with different request data"
}
}
Business Logic Errors
Status: 400Payment verification failed.{
"error": {
"code": "verification_failed",
"message": "Transaction amount does not match expected amount",
"details": {
"expected": "1000000000000000000",
"actual": "500000000000000000"
}
}
}
Status: 400Settlement failed or not allowed.{
"error": {
"code": "settlement_failed",
"message": "Cannot settle payment with status: pending",
"details": {
"verification_id": "ver_abc123",
"current_status": "pending"
}
}
}
Status: 400Insufficient funds for settlement.{
"error": {
"code": "insufficient_funds",
"message": "Insufficient funds for settlement"
}
}
Server Errors (5xx)
Status: 500Internal server error.{
"error": {
"code": "internal_error",
"message": "An internal error occurred"
}
}
Status: 502Error from upstream provider (1Shot).{
"error": {
"code": "upstream_error",
"message": "Upstream service unavailable"
}
}
Status: 504Request timeout.{
"error": {
"code": "timeout",
"message": "Request timeout"
}
}
Error Handling Best Practices
async function verifyPayment(data) {
try {
const response = await fetch("https://facilitator.api.0xmeta.ai/v1/verify", {
method: "POST",
headers: {
"Content-Type": "application/json",
"X-API-Key": API_KEY,
"Idempotency-Key": `verify_${Date.now()}`,
},
body: JSON.stringify(data),
});
const result = await response.json();
// Check for errors
if (!response.ok) {
handleError(response.status, result.error);
return null;
}
return result;
} catch (error) {
console.error("Network error:", error);
throw error;
}
}
function handleError(status, error) {
switch (error.code) {
case "unauthorized":
console.error("Invalid API key");
break;
case "rate_limited":
console.error(
"Rate limited, retry after:",
response.headers.get("Retry-After")
);
break;
case "verification_failed":
console.error("Verification failed:", error.details);
break;
case "upstream_error":
console.error("Upstream error, retry later");
break;
default:
console.error("Error:", error.message);
}
}
Retry Strategy
For transient errors (5xx, rate limits), implement exponential backoff:
async function retryRequest(fn, maxRetries = 3) {
for (let attempt = 0; attempt < maxRetries; attempt++) {
try {
return await fn();
} catch (error) {
const shouldRetry =
error.status >= 500 ||
error.status === 429 ||
error.code === "ETIMEDOUT";
if (!shouldRetry || attempt === maxRetries - 1) {
throw error;
}
// Exponential backoff: 1s, 2s, 4s
const delay = Math.pow(2, attempt) * 1000;
await new Promise((resolve) => setTimeout(resolve, delay));
}
}
}
// Usage
const result = await retryRequest(() => verifyPayment(data));
Don’t retry on 4xx errors (except 429). These indicate problems with your
request.
Use idempotency keys when retrying to prevent duplicate operations.