Skip to main content

Error Codes Reference

Complete reference of all HTTP status codes and error responses.

Complete reference of all error codes returned by Paysera Checkout APIs.

HTTP Status Codes​

CodeNameRetryDescription
200OK-Request successful
201Created-Resource created successfully
400Bad RequestNoMalformed request syntax
401UnauthorizedMaybe*Authentication failed
403ForbiddenNoInsufficient permissions
404Not FoundNoResource does not exist
409ConflictNoResource conflict (e.g., duplicate)
422Unprocessable EntityNoValidation error
429Too Many RequestsYesRate limit exceeded
500Internal Server ErrorYesServer-side error
502Bad GatewayYesUpstream service error
503Service UnavailableYesService temporarily unavailable

*Retry after refreshing access token

Error Response Format​

Most errors use the simple envelope:

{
"error": "error_code",
"error_description": "Human-readable description"
}

Validation errors include per-field details under error_properties (a map of field path → list of message strings):

{
"error": "invalid_request",
"error_description": "Validation failed",
"error_properties": {
"purchase.amount": ["Amount should be greater than 0"],
"purchase.currency": ["Currency is required"]
}
}

Authentication Errors​

Error CodeHTTP StatusMessageSolution
invalid_client401Invalid client credentialsVerify client_id and client_secret
invalid_token401Token is expiredRequest new access token
invalid_token401Token validation failedCheck token format and environment
invalid_grant401Invalid grant typeUse client_credentials grant
unauthorized401Authorization requiredInclude Authorization header

Validation Errors​

Error CodeHTTP StatusCommon FieldsDescription
invalid_request400VariousOne or more fields failed validation. Per-field details are returned in error_properties.

Common Field Errors​

FieldError MessageSolution
project_idProject is requiredInclude project_id in request or ensure your JWT token contains a project
project_idProject not foundVerify project ID exists and you have access
purchase.amountAmount must be greater than 0Use positive amount in minor units
purchase.amountInvalid amount formatUse whole number string (e.g., "1000" for €10.00)
purchase.currencyCurrency is requiredInclude currency code
purchase.currencyInvalid currencyUse valid ISO 4217 code
purchase.referenceReference is requiredInclude unique reference
redirect_urls.success_urlInvalid URL formatUse valid HTTPS URL
redirect_urls.callback_urlInvalid URL formatUse valid HTTPS URL
lifetimeLifetime must be positiveUse positive integer
experience.languageInvalid language codeUse supported language

Resource Errors​

Error CodeHTTP StatusMessageDescription
not_found404Order not foundOrder ID does not exist
not_found404Payment link not foundLink ID does not exist
not_found404Project not foundProject ID does not exist

Business Logic Errors​

Error CodeHTTP StatusMessageSolution
conflict409Order with reference existsUse unique reference
conflict409Order already completedOrder cannot be modified

Rate Limiting Errors​

Rate limiting is enforced at the API gateway. On throttle, the gateway returns 429 Too Many Requests with a Retry-After header indicating the number of seconds to wait before retrying.

HeaderDescription
Retry-AfterSeconds to wait before retry

Rate Limit Handling Examples​

Implement exponential backoff when encountering rate limits:

<?php

class RateLimitHandler
{
private int $maxRetries = 3;
private int $baseDelay = 1000; // milliseconds

public function executeWithRetry(callable $request): mixed
{
$attempt = 0;

while ($attempt < $this->maxRetries) {
try {
return $request();
} catch (RateLimitException $e) {
$attempt++;

if ($attempt >= $this->maxRetries) {
throw $e;
}

$delay = $this->calculateDelay($attempt, $e->getRetryAfter());
usleep($delay * 1000);
}
}
}

private function calculateDelay(int $attempt, ?int $retryAfter): int
{
if ($retryAfter !== null) {
return $retryAfter * 1000; // Convert seconds to milliseconds
}

// Exponential backoff: 1s, 2s, 4s...
return $this->baseDelay * pow(2, $attempt - 1);
}
}

// Usage
$handler = new RateLimitHandler();
$result = $handler->executeWithRetry(function() use ($client, $payload) {
return $client->createOrder($payload);
});

Server Errors​

HTTP StatusDescriptionSolution
500Internal server errorRetry with backoff
502Bad gateway (upstream service unreachable)Retry with backoff
503Service temporarily unavailableRetry with backoff

Server-side errors return the simple envelope (error, error_description).

Error Handling by Type​

PHP Example​

<?php

function handleError(int $httpCode, array $body): never
{
$error = $body['error'] ?? 'unknown_error';
$description = $body['error_description'] ?? 'Unknown error';
$properties = $body['error_properties'] ?? [];

match (true) {
$httpCode === 401 => throw new AuthenticationException($description),
$httpCode === 403 => throw new AuthorizationException($description),
$httpCode === 404 => throw new NotFoundException($description),
$httpCode === 409 => throw new ConflictException($description),
$httpCode === 400 => throw new ValidationException($description, $properties),
$httpCode === 429 => throw new RateLimitException($description),
default => throw new ApiException($description, $httpCode),
};
}

JavaScript Example​

function handleError(response, body) {
const { error, error_description, error_properties } = body;

switch (response.status) {
case 401:
throw new AuthenticationError(error_description);
case 403:
throw new AuthorizationError(error_description);
case 404:
throw new NotFoundError(error_description);
case 409:
throw new ConflictError(error_description);
case 400:
throw new ValidationError(error_description, error_properties);
case 429:
throw new RateLimitError(error_description, response.headers.get('Retry-After'));
default:
throw new ApiError(error_description, response.status);
}
}

User-Friendly Messages​

Error CodeUser Message
invalid_clientUnable to authenticate. Please contact support.
invalid_tokenSession expired. Please try again.
invalid_requestPlease check your input and try again.
not_foundThe requested item was not found.
conflictThis action cannot be completed. The item may already exist.
429 Too Many RequestsToo many requests. Please wait a moment.
500/502/503Service temporarily unavailable. Please try again.

Troubleshooting Guide​

SymptomCheckSolution
401 on all requestsCredentialsVerify client_id/secret
401 after workingTokenRefresh access token
400 with amountFormatUse minor units as string (e.g., "1000" for €10.00)
400 with URLProtocolUse HTTPS URLs
404 on orderIDVerify order UUID
409 on createReferenceUse unique reference
429 frequentlyRequest rateImplement rate limiting