Skip to main content

Error Response Format

All error responses follow a consistent JSON structure:
{
  "error": {
    "code": "ERROR_CODE",
    "message": "Human-readable error message",
    "details": {}
  }
}

Fields

error.code
string
required
Machine-readable error code (e.g., VALIDATION_ERROR, NOT_FOUND)
error.message
string
required
Human-readable error description
error.details
object
Additional error context (validation errors, field-specific issues)

Error Codes

The API uses standard HTTP status codes along with application-specific error codes.

400 Bad Request

Code: VALIDATION_ERROR Request validation failed. The details field contains information about which fields failed validation. Example:
{
  "error": {
    "code": "VALIDATION_ERROR",
    "message": "Invalid proposal input",
    "details": {
      "formErrors": [],
      "fieldErrors": {
        "amount.value": ["Required"]
      }
    }
  }
}
Common Causes:
  • Missing required fields
  • Invalid field types or formats
  • Value out of acceptable range
  • Invalid query parameters

401 Unauthorized

Code: UNAUTHORIZED Authentication failed or is required. Example:
{
  "error": {
    "code": "UNAUTHORIZED",
    "message": "Invalid API key"
  }
}
Common Causes:
  • Missing Authorization header
  • Invalid API key
  • Deactivated merchant account

404 Not Found

Code: NOT_FOUND The requested resource does not exist. Example:
{
  "error": {
    "code": "NOT_FOUND",
    "message": "Name \"alice\" not found"
  }
}
Common Causes:
  • Name not registered
  • Proposal/transaction ID not found
  • Payment request not found
  • Merchant address not registered

409 Conflict

Code: CONFLICT The request conflicts with existing data. Example:
{
  "error": {
    "code": "CONFLICT",
    "message": "A merchant with this hostname already exists"
  }
}
Common Causes:
  • Duplicate merchant hostname
  • Name already registered (on-chain conflict)

500 Internal Server Error

Code: INTERNAL_ERROR or SUI_ERROR An unexpected server error occurred. Example:
{
  "error": {
    "code": "INTERNAL_ERROR",
    "message": "An unexpected error occurred"
  }
}
Example (Sui Error):
{
  "error": {
    "code": "SUI_ERROR",
    "message": "Failed to submit transaction to Sui network",
    "details": {
      "digest": "...",
      "error": "..."
    }
  }
}
Common Causes:
  • Database connection failure
  • Sui RPC error
  • On-chain transaction failure
  • Service unavailability

Error Classes

The backend defines the following error classes (see errors/index.ts:1-47):

AppError

Base error class for all application errors.
class AppError extends Error {
  constructor(
    public readonly statusCode: number,
    public readonly code: string,
    message: string,
    public readonly details?: unknown,
  )
}

NotFoundError

Status: 404
Code: NOT_FOUND
Used when a requested resource does not exist.

ValidationError

Status: 400
Code: VALIDATION_ERROR
Used when request validation fails (invalid input).

AuthError

Status: 401
Code: UNAUTHORIZED
Used when authentication fails or is missing.

ConflictError

Status: 409
Code: CONFLICT
Used when the request conflicts with existing data.

SuiError

Status: 500
Code: SUI_ERROR
Used when Sui blockchain operations fail.

Domain-Specific Errors

Expired Proposals

When fetching an expired proposal via /intents/:txId: Status: 400 Bad Request
{
  "error": {
    "code": "VALIDATION_ERROR",
    "message": "Proposal has expired"
  }
}

Cancelled Proposals

Status: 400 Bad Request
{
  "error": {
    "code": "VALIDATION_ERROR",
    "message": "Proposal has been cancelled"
  }
}

Expired Payment Requests

Status: 400 Bad Request
{
  "error": {
    "code": "VALIDATION_ERROR",
    "message": "Payment request has expired"
  }
}

Invalid Payment Request Status

Status: 400 Bad Request
{
  "error": {
    "code": "VALIDATION_ERROR",
    "message": "Payment request is paid"
  }
}

Handling Errors

Client-Side Error Handling

try {
  const response = await fetch('/api/identipay/v1/names/alice');
  const data = await response.json();
  
  if (!response.ok) {
    const error = data.error;
    
    switch (error.code) {
      case 'NOT_FOUND':
        console.error('Name not registered:', error.message);
        break;
      case 'VALIDATION_ERROR':
        console.error('Validation failed:', error.details);
        break;
      default:
        console.error('Unexpected error:', error.message);
    }
    
    return;
  }
  
  // Success
  console.log('Name resolved:', data);
} catch (err) {
  console.error('Network error:', err);
}

Validation Error Details

Validation errors include a details field with the validation failure information from Zod:
{
  "error": {
    "code": "VALIDATION_ERROR",
    "message": "Invalid merchant registration input",
    "details": {
      "formErrors": [],
      "fieldErrors": {
        "name": ["String must contain at least 1 character(s)"],
        "suiAddress": ["Invalid"],
        "publicKey": ["Must be 64-char lowercase hex"]
      }
    }
  }
}

Best Practices

Always check the HTTP status code first, then inspect the error code
Use the details field for field-level validation errors
Log full error responses for debugging but show user-friendly messages to end users
Implement retry logic for SUI_ERROR and INTERNAL_ERROR (transient failures)
Do not retry VALIDATION_ERROR, NOT_FOUND, UNAUTHORIZED, or CONFLICT errors

Build docs developers (and LLMs) love