Skip to main content

Documentation Index

Fetch the complete documentation index at: https://lyelpay.mintlify.app/llms.txt

Use this file to discover all available pages before exploring further.

All Lyel Pay API errors follow a consistent format. The code field is a stable string from the @lyelpay/errors package — it won’t change between versions, so it’s safe to key business logic on it.

Error response format

{
  "statusCode": 422,
  "message": "Insufficient funds",
  "code": "E_INSUFFICIENT_FUNDS"
}
FieldTypeDescription
statusCodenumberHTTP status code
messagestringHuman-readable description
codestringStable error code — use this in your switch statements

Using typed error codes

Install the errors package to get autocompletion and type safety:
npm install @lyelpay/errors
Then match errors by code:
import { ErrorCodes } from '@lyelpay/errors';

try {
  await lyel.charge({ intentionId });
} catch (err) {
  switch (err.code) {
    case ErrorCodes.E_INSUFFICIENT_FUNDS:
      showToast('Your wallet balance is too low. Please top up and try again.');
      break;
    case ErrorCodes.E_INVALID_OTP:
      showToast('Invalid code. Please check and try again.');
      break;
    case ErrorCodes.E_OTP_EXPIRED:
      showToast('Your code has expired. Request a new one.');
      break;
    case ErrorCodes.E_OTP_BLOCKED:
      showToast('Too many attempts. Please wait before trying again.');
      break;
    case ErrorCodes.E_ACCOUNT_BLOCKED:
      showToast('This account has been blocked. Contact support.');
      break;
    default:
      console.error('Unexpected error:', err.code, err.message);
  }
}

Common errors by scenario

Authentication

CodeHTTPWhen it happens
E_INVALID_API_KEY401API key is wrong or revoked
E_UNAUTHORIZED401No valid token on a protected endpoint
E_JWT_EXPIRED401JWT has expired — re-authenticate
E_JWT_INVALID401JWT is malformed or tampered
E_FORBIDDEN403Valid token but insufficient permissions

Payments

CodeHTTPWhen it happens
E_INSUFFICIENT_FUNDS422Payer’s wallet balance too low
E_SELF_PAYMENT422Sender and recipient are the same account
E_INVALID_AMOUNT422Amount is zero, negative, or exceeds limits
E_MAX_AMOUNT_EXCEEDED422Above daily/transaction cap
E_MONTHLY_LIMIT_EXCEEDED422User’s monthly transfer limit reached
E_CREATE_PAYMENT_FAILED500Internal error creating the payment
E_INTENTION_NOT_FOUND404The intentionId doesn’t exist or has expired

OTP

CodeHTTPWhen it happens
E_INVALID_OTP422Wrong OTP code entered
E_OTP_EXPIRED422OTP has passed its validity window
E_OTP_BLOCKED429Too many failed OTP attempts
E_OTP_COOLDOWN429Too soon to request another OTP
E_MAX_DAILY_ATTEMPTS429Daily OTP request limit reached

Accounts

CodeHTTPWhen it happens
E_ACCOUNT_NOT_FOUND404User ID or phone number not found
E_ACCOUNT_BLOCKED403Account is temporarily suspended
E_ACCOUNT_PERMANENTLY_BLOCKED403Account is permanently disabled
E_ACCOUNT_NOT_ACTIVATED403Account created but not yet verified
E_KYC_LEVEL_INSUFFICIENT403Operation requires a higher KYC tier

Withdrawals

CodeHTTPWhen it happens
E_WITHDRAW_INSUFFICIENT_FUNDS422Not enough balance to withdraw
E_WITHDRAW_DAILY_LIMIT_REACHED422Daily withdrawal cap hit
E_WITHDRAW_NOT_FOUND404Withdrawal ID doesn’t exist
E_WITHDRAW_FORBIDDEN403Account not authorized to withdraw

Webhooks

CodeHTTPWhen it happens
E_INVALID_TOKEN401Webhook signature verification failed

HTTP status codes

StatusMeaning
200Success
201Created
400Bad request (malformed body, missing fields)
401Unauthenticated
403Authenticated but not authorized
404Resource not found
422Validation error or business rule violation
429Rate limit or cooldown
500Internal server error — contact support if persistent

Full error code list

All error codes are exported from @lyelpay/errors:
import { ErrorCodes, ErrorCode } from '@lyelpay/errors';

// ErrorCode is the union type of all possible code values
function handleError(code: ErrorCode) {
  // TypeScript will warn you if you mistype a code
}
The package exports ErrorCodes (the object) and ErrorCode (the type). Error codes are stable API contracts — they will not be renamed or removed.
E_ACCOUNT_ALREADY_VERIFIED
E_ACCOUNT_BLOCKED
E_ACCOUNT_NOT_ACTIVATED
E_ACCOUNT_NOT_ACTIVATED_OR_BLOCKED
E_ACCOUNT_NOT_FOUND
E_ACCOUNT_PERMANENTLY_BLOCKED
E_API_KEY_NOT_FOUND
E_API_KEY_REVOKE_ERROR
E_BAD_GATEWAY_SMS
E_BANK_DETAILS_REQUIRED
E_BENEFICIARY_ACCOUNT_BLOCKED
E_CANCEL_DEPOSIT_FAILED
E_CANNOT_AUTHENTICATE
E_COMMISSION_NOT_FOUND
E_COMPANY_ALREADY_EXISTS
E_COMPANY_NOT_FOUND
E_CONTACT_ALREADY_EXISTS
E_COUNTRY_NOT_AUTHORIZED
E_COUNTRY_UNKNOWN
E_CREATE_PAYMENT_FAILED
E_DEPOSIT_ALREADY_RETRIED
E_DEPOSIT_FAILED
E_DEPOSIT_NOT_CANCELLABLE
E_DEPOSIT_NOT_FOUND
E_DEPOSIT_NOT_RETRYABLE
E_DEPOSIT_TO_YOURSELF
E_EMAIL_EXISTS
E_FAILED_TO_CREATE_ACCOUNT
E_FORBIDDEN
E_GEO_RESTRICTED
E_INSUFFICIENT_FUNDS
E_INTENTION_NOT_FOUND
E_INTERNAL_SERVER_ERROR
E_INVALID_AMOUNT
E_INVALID_API_KEY
E_INVALID_OTP
E_INVALID_PASSWORD
E_INVALID_PERMISSIONS
E_INVALID_PHONE_NUMBER
E_INVALID_PROVIDER
E_INVALID_REFRESH_TOKEN
E_JWT_EXPIRED
E_JWT_INVALID
E_KYC_ALREADY_APPROVED
E_KYC_DOCUMENT_NOT_FOUND
E_KYC_FLAGGED
E_KYC_LEVEL_INSUFFICIENT
E_KYC_TIER_LIMIT_EXCEEDED
E_LEDGER_FAILED
E_MAX_AMOUNT_EXCEEDED
E_MAX_DAILY_ATTEMPTS
E_MERCHANT_BLOCKED
E_MERCHANT_INACTIVE
E_MERCHANT_INSUFFICIENT_BALANCE
E_MERCHANT_NOT_FOUND
E_MONTHLY_LIMIT_EXCEEDED
E_NOT_FOUND
E_OPERATION_TYPE_MISMATCH
E_OTP_BLOCKED
E_OTP_COOLDOWN
E_OTP_EXPIRED
E_PAYMENT_ALREADY_REFUNDED
E_PAYMENT_NOT_FOUND
E_PAYMENT_NOT_REFUNDABLE
E_PHONE_EXISTS
E_PROFILE_NOT_FOUND
E_REFUND_AMOUNT_EXCEEDS_ORIGINAL
E_SAME_USER
E_SELF_PAYMENT
E_TOO_FREQUENT_TRANSACTIONS
E_UNAUTHORIZED
E_USER_NOT_FOUND
E_WITHDRAW_DAILY_LIMIT_REACHED
E_WITHDRAW_FORBIDDEN
E_WITHDRAW_INSUFFICIENT_FUNDS
E_WITHDRAW_NOT_FOUND
E_WRONG_PASSWORD