PayzCore Docs

Error Reference

Complete API error reference. HTTP status codes, error response format, common error messages, rate limit headers, and how SDKs map errors to typed exceptions.

Error Reference

All PayzCore API errors follow a consistent JSON format. This page documents every error status code, the response structure, common error messages, and how to handle them.

Response Format

Every error response includes an error field with a human-readable message. Some errors include additional fields for context.

Standard Error

{
  "error": "Description of what went wrong"
}

Validation Error

When the request body fails validation (wrong type, missing required field, value out of range), the API returns a single generic message. It does not list the failing fields, so check your request against the API Reference.

{
  "error": "Invalid request body"
}

Rate Limit Error (with plan info)

{
  "error": "Daily API call limit exceeded. Upgrade your plan for unlimited access.",
  "limit": 500,
  "plan": "free"
}

HTTP Status Codes

400 Bad Request

Validation errors caused by invalid parameters, missing required fields, or unsupported values.

Error MessageCause
Invalid request bodyJSON parse error or schema validation failure (wrong type, missing required field, value out of range).
USDC is not supported on TRC20Unsupported network+token combination. See Supported Networks.
Amount must be at least $X.XX (project minimum)Payment amount is below the project's configured minAmount.
Project has no wallet assignedThe project needs a wallet before creating payments.
Wallet not foundThe wallet linked to the project was deleted or is missing.
Wallet has no xPub configured for this networkThe wallet is missing the xPub key for the requested network's address family (tron or evm).
Amount has more decimal places than this project's micro-amount precision allowsPool + micro_amount mode: the base amount has more decimals than the project's micro-amount precision (send e.g. 50 or 50.5, PayzCore adds the offset).
Specified address does not belong to this project's walletThe address parameter (dedicated mode) references an address not in the wallet's static address pool.
No addresses available for this network. Contact merchant.No static address is registered for this network, or all are already assigned (dedicated mode).
Invalid limit or offsetPagination parameters must be positive integers. limit max is 100.
Invalid status filterStatus must be one of: pending, confirming, partial, paid, overpaid, expired, cancelled.
Invalid created_afterDate parameter is not a valid ISO 8601 string.
Invalid updated_afterDate parameter is not a valid ISO 8601 string.

How to fix: Compare your request with the API Reference (types, required fields, limits). Correct the request parameters and retry.

401 Unauthorized

Authentication failed. The API key is missing, invalid, or malformed.

Error MessageCause
Missing x-api-key headerThe x-api-key header was not included in the request.
Invalid API keyThe API key does not match any active project.

Too many requests with unknown API keys from one IP (30 per minute) return 429 Too many invalid API key attempts. Try again later. instead.

How to fix: Verify your API key is correct and included in the x-api-key header. API keys start with pk_live_. If you lost your key, the project owner can regenerate it from the project settings.

403 Forbidden

The request was authenticated but is not allowed due to access restrictions.

Error MessageCause
Project is deactivatedAn admin has deactivated this project.
Account suspended. Contact support.The project owner's account has been suspended.
Account is no longer active.The project owner's account was deleted or closed.

How to fix: Contact PayzCore support or your account administrator. Deactivated projects cannot make API calls until reactivated.

404 Not Found

The requested resource does not exist or is not accessible by this API key.

Error MessageCause
Payment not foundThe payment ID does not exist or belongs to a different project.

How to fix: Verify the payment ID is correct. Each project can only access its own payments.

409 Conflict

The request conflicts with an existing resource.

EndpointError MessageCause
POST /v1/paymentsPayment already exists with different amountA pending payment with the same identifiers exists but with another amount. The body also has existing_amount.
POST /v1/paymentsexternal_order_id is already in use with a different external_refThe external_order_id belongs to another customer reference.
POST /v1/paymentsThis address is already assigned to a different customerDedicated mode: the address you passed is assigned to another external_ref.
POST /v1/paymentsThis customer already has a payment in progress on this network. Cancel it or wait for it to complete.per_user / dedicated modes: the same external_ref already has a pending/confirming/partial payment on this network+token for a different order (other amount or external_order_id). The body also has existing_payment_id and existing_amount. Cancel it (PATCH) or reuse it.
PATCH /v1/payments/:idCannot cancel payment with status "X". Only pending payments can be cancelled.Only pending payments can be cancelled.
PATCH /v1/payments/:idPayment status changed before cancellation could complete. Please refresh and try again.The payment changed state while it was being cancelled.
POST /v1/payments/:id/confirmTransaction hash already submitted and pending confirmationA tx hash was already submitted for this payment. The body also has submitted_tx_hash.
POST /v1/payments/:id/confirmThis transaction hash is already submitted for another payment / This transaction hash is already associated with another paymentThe same tx hash cannot confirm two payments.
POST /v1/payments/:id/confirmPayment already finalizedThe payment reached a final status while the hash was being checked.

Repeating a request is not a 409. When you send the same external_order_id + external_ref + network + token (and amount) again, PayzCore returns 200 with the existing payment and "existing": true. This makes retries safe. The SDKs map every 409 above to IdempotencyError / IdempotencyException; read its message for the exact reason.

429 Too Many Requests

Rate limit exceeded. There are two types of rate limits:

Per-Minute Rate Limit (burst protection)

Limits the number of requests per API key per minute. Default: 60 requests/minute.

{
  "error": "Rate limit exceeded. Try again later."
}

Response headers (sent only on 429 responses, not on successful ones):

HeaderValueDescription
X-RateLimit-Limit60Maximum requests per window
X-RateLimit-Remaining0Remaining requests in current window
X-RateLimit-Reset1708444800Unix timestamp (seconds) when the window resets

Daily Limit (plan-based)

Limits total API calls per day based on your plan.

{
  "error": "Daily API call limit exceeded. Upgrade your plan for unlimited access.",
  "limit": 500,
  "plan": "free"
}

Response headers (only on 429 responses):

HeaderValueDescription
X-RateLimit-Limit500Daily limit for your plan
X-RateLimit-Remaining0Remaining calls today
X-RateLimit-Reset1708473600Unix timestamp (seconds) when the daily counter resets (midnight UTC)
X-RateLimit-DailytrueIndicates this is a daily limit (not per-minute)

Plan limits:

PlanAPI Calls/DayWebhooks/Day
Free50050
Pro5,0001,000

Admin-configured custom overrides may apply per user.

Capacity Limit (pool mode)

When using pool+micro_amount mode, all available offsets for the requested amount may be exhausted. This 429 has no X-RateLimit-* headers:

{
  "error": "Payment capacity exceeded. Please try again later."
}

How to fix for per-minute limits: Wait for the reset time indicated in the X-RateLimit-Reset header. Implement exponential backoff in your client.

How to fix for daily limits: Wait until midnight UTC, or upgrade to the Pro plan for higher limits.

How to fix for capacity limits: Wait for existing payments on the pool to resolve (paid/expired), or add more static addresses.

500 Internal Server Error

An unexpected error occurred on the server.

{
  "error": "Failed to create payment"
}

How to fix: Retry the request with exponential backoff. If the error persists, check the health endpoint and contact support.

Recommended retry strategy:

AttemptDelay
11 second
22 seconds
34 seconds
48 seconds
5Give up, alert your team

SDK Error Handling

The official SDKs map HTTP errors to typed exception classes, making it easy to handle specific error types.

Node.js SDK

import {
  PayzCoreError,
  ValidationError,
  AuthenticationError,
  ForbiddenError,
  NotFoundError,
  RateLimitError,
  IdempotencyError,
} from '@payzcore/node'

try {
  const payment = await payzcore.payments.create({
    amount: 50,
    network: 'TRC20',
    externalRef: 'customer-123',
  })
} catch (err) {
  if (err instanceof ValidationError) {
    // 400 - Invalid parameters
    console.error('Validation:', err.message)
  } else if (err instanceof AuthenticationError) {
    // 401 - Invalid API key
    console.error('Auth:', err.message)
  } else if (err instanceof ForbiddenError) {
    // 403 - Project inactive or account suspended
    console.error('Forbidden:', err.message)
  } else if (err instanceof NotFoundError) {
    // 404 - Resource not found
    console.error('Not found:', err.message)
  } else if (err instanceof RateLimitError) {
    // 429 - Rate limited
    console.error('Rate limited:', err.message)
    // retryAfter is a Unix timestamp (seconds), not a duration
    const waitSeconds = Math.max(0, (err.retryAfter ?? 0) - Math.floor(Date.now() / 1000))
    console.error('Retry in', waitSeconds, 'seconds. Daily limit:', err.isDaily)
  } else if (err instanceof IdempotencyError) {
    // 409 - Conflict (see the 409 table above)
    console.error('Conflict:', err.message)
  } else if (err instanceof PayzCoreError) {
    // Other API errors (500, etc.)
    console.error('API error:', err.status, err.message)
  }
}

Error Class Hierarchy

HTTP StatusSDK ClassProperties
400ValidationErrormessage, status, code
401AuthenticationErrormessage, status, code
403ForbiddenErrormessage, status, code
404NotFoundErrormessage, status, code
409IdempotencyErrormessage, status, code
429RateLimitErrormessage, status, code, retryAfter (Unix timestamp in seconds, from X-RateLimit-Reset), isDaily (boolean)
OtherPayzCoreErrormessage, status, code

All error classes extend PayzCoreError, which extends Error. You can catch PayzCoreError as a catch-all for any API error.

Python SDK

import time
from payzcore import PayzCoreError, ValidationError, RateLimitError

try:
    payment = client.payments.create(
        amount=50, network="TRC20", external_ref="customer-123"
    )
except ValidationError as e:
    print(f"Validation: {e.message}")
except RateLimitError as e:
    # retry_after is a Unix timestamp (seconds), not a duration
    wait = max(0, (e.retry_after or 0) - int(time.time()))
    print(f"Rate limited, retry in {wait}s")
except PayzCoreError as e:
    print(f"API error {e.status}: {e.message}")

PHP SDK

use PayzCore\Exceptions\ValidationException;
use PayzCore\Exceptions\RateLimitException;
use PayzCore\Exceptions\PayzCoreException;

try {
    $payment = $client->payments->create([
        'amount' => 50, 'network' => 'TRC20', 'externalRef' => 'customer-123'
    ]);
} catch (ValidationException $e) {
    echo "Validation: " . $e->getMessage();
} catch (RateLimitException $e) {
    // getRetryAfter() is a Unix timestamp (seconds), not a duration
    $wait = max(0, ($e->getRetryAfter() ?? time()) - time());
    echo "Rate limited, retry in {$wait}s";
} catch (PayzCoreException $e) {
    echo "API error {$e->getStatusCode()}: {$e->getMessage()}";
}

Best Practices

  1. Always check the status code first. Different status codes require different handling strategies.
  2. Read the error message on 400 errors. Validation failures return Invalid request body without field details, so compare your request with the API Reference.
  3. Implement retry logic for 429 and 500 errors. Use the X-RateLimit-Reset header for rate limits and exponential backoff for server errors.
  4. Do not retry 400, 401, 403, or 404 errors. These indicate issues that need to be fixed in your code or configuration, not transient failures.
  5. Use external_order_id for idempotency. This prevents duplicate payment creation during retries and returns the existing payment safely.
  6. Log error responses. Store the full error response body for debugging and support requests.
  7. Use typed SDK exceptions. The official SDKs provide specific error classes that make error handling clean and type-safe.

On this page