Errors
All errors share the same JSON envelope, whatever the endpoint.
{
"message": "Promo code already exists",
"errorCode": "400:PROMO_CODE_ALREADY_EXISTS",
"path": "/coupons",
"date": "2026-01-15T09:30:00.000Z"
}
| Field | Type | Description |
|---|---|---|
message | string | Human-readable message, translated according to x-lang. Display it, don't test it. |
errorCode | string | <HTTP status>:<CODE>. Stable: this is the field your code should test. |
path | string | The URL called, including the query string. |
date | string | ISO 8601 timestamp. |
details | object | Optional. Values that help with diagnosis (e.g. remaining credits). |
validationErrors | array | Only present for 400:VALIDATION_ERROR: [{field, message}]. |
Validation errors
{
"message": "email must be an email",
"errorCode": "400:VALIDATION_ERROR",
"path": "/clients",
"date": "2026-01-15T09:30:00.000Z",
"validationErrors": [
{"field": "email", "message": "email must be an email"},
{"field": "lastName", "message": "lastName must be longer than or equal to 2 characters"}
]
}
message repeats the first error. For nested objects, field holds the name of the leaf field (backgroundColor), not the full path.
Handle errors properly
const res = await fetch(url, options);
if (!res.ok) {
const err = await res.json();
const [, code] = err.errorCode.split(':');
switch (code) {
case 'UNAUTHORIZED':
// token expired: log in again
break;
case 'VALIDATION_ERROR':
// fix the fields listed in err.validationErrors
break;
case 'PASS_BUILDER_ERROR':
// temporary pass generation error: retry later
break;
default:
throw new Error(`${err.errorCode}: ${err.message}`);
}
}
- 4xx: the request is at fault. Don't resend it as is.
- 5xx: an error on eldo wallet's side. Retry with an increasing delay (1 s, 2 s, 4 s…).
- Each page of the API reference lists the errors specific to that endpoint, with a sample response.
All codes
| HTTP | messageCode | Message | What to do |
|---|---|---|---|
204 | NOTHING_TO_UPDATE | Nothing to update! | |
400 | ACTIVE_WELCOME_COUPON_ALREADY_EXISTS | Active welcome coupon already exists | |
400 | ALL_CLIENTS_ALREADY_HAVE_COUPON | All provided clients already have this coupon | |
400 | ARRIVAL_TIME_MUST_BE_AFTER_DEPARTURE_TIME_CONSIDERING_DATES | Arrival time must be after departure time considering dates | |
400 | BATCH_LIMIT_EXCEEDED | Batch limit exceeded (max 100) | |
400 | CENTER_ROW_IS_REQUIRED | Center row is required | |
400 | CHECKOUT_MUST_BE_AFTER_CHECKIN | Checkout must be after checkin | |
400 | CLIENT_DOES_NOT_BELONG_TO_THIS_WALLET | Client does not belong to this wallet | |
400 | CLIENTS_EXIST_FOR_THIS_CARD_TYPE | Clients exist for this card type | |
400 | COMMUNICATION_DELETED | Communication is deleted and cannot be updated | |
400 | DEFAULT_CLIENT_TYPE_REQUIRED | At least one client type must remain default | |
400 | ERROR_CUSTOMER_TYPE_ASSIGNMENT | Error customer type assignment | |
400 | FILE_REQUIRED | File is required | |
400 | HOTEL_HAS_PASSES | Hotel has passes! | |
400 | INSTANT_COMMUNICATION_ALREADY_EXISTS | Instant communication already exists | |
400 | INSUFFICIENT_CREDIT | Insufficient {creditType} credit: {required} required, {remaining} remaining | |
400 | INVALID_DATE_RANGE | endDate must be on or after startDate. | |
400 | INVALID_DEPARTURE_OR_ARRIVAL_DATETIME_FORMAT | Invalid departure or arrival datetime format | |
400 | INVALID_DEVICE_TYPE | Invalid device type: {deviceType} | |
400 | INVALID_JSON | Invalid JSON syntax in request body | |
400 | INVALID_MULTIPART | Invalid multipart request: missing or malformed boundary in Content-Type header. Use multipart/form-data with a valid boundary for file uploads, or application/json for JSON-only updates. | |
400 | INVALID_PASS_KIND | Invalid pass kind | |
400 | INVALID_PASS_TYPE | Invalid pass type: {passType} | |
400 | INVALID_STATUS | Invalid status provided | |
400 | INVALID_WALLET_OBJECT_TYPE | Invalid wallet object type: {objectType} | |
400 | LEFT_ROW_IS_REQUIRED | Left row is required | |
400 | MAX_WALLET_LOCATIONS_REACHED | Max wallet locations reached | |
400 | MISSING_ANDROID_OBJECT_ID | Missing Android object ID | |
400 | MISSING_BARCODE | Missing barcode | |
400 | MISSING_RECIPIENT_DETAILS_FOR_NON_CLIENT | Missing recipient details (firstName, lastName, email) for non-client recipient | |
400 | MISSING_REQUIRED_FIELDS | Missing required fields: {fields} | |
400 | NO_CLIENTS_FOUND | No clients found | |
400 | NO_CUSTOMERS_FOUND | No customers found | |
400 | NO_PASS_DATA_PROVIDED | No pass data provided | |
400 | NO_RECIPIENTS_PROVIDED | No recipients provided | |
400 | OPERATION_TYPE_NOT_ALLOWED | operationType is only allowed when transactionType is OPERATION | |
400 | OPERATION_TYPE_REQUIRED | operationType is required when transactionType is OPERATION | |
400 | PACK_ALREADY_EXISTS | Pack name already exists | |
400 | PACK_INSUFFICIENT_CREDITS | Cannot assign pack: this wallet has {clientsCount} clients, but the pack's {creditTypes} credit(s) allow fewer than that | |
400 | PASS_ALREADY_CANCELED | Cannot update a canceled pass | |
400 | PASS_ALREADY_EXPIRED | Pass already expired | |
400 | PASS_ALREADY_GENERATED | Pass already generated | |
400 | PASS_ALREADY_REDEEMED | Pass is already redeemed | |
400 | PASS_NOT_REDEEMED | Pass is not redeemed | |
400 | PROMO_CODE_ALREADY_EXISTS | Promo code already exists | |
400 | RIGHT_ROW_IS_REQUIRED | Right row is required | |
400 | SCHEDUle_DATE_PASSED | Schedule date has already passed | |
400 | SMS_CONFIG_REQUIRED | SMS configuration is required | |
400 | SMS_CREDENTIALS_NOT_CONFIGURED | SMS credentials are not configured for this wallet | |
400 | SMS_TITLE_IS_REQUIRED | SMS title is required | |
400 | SYNC_EXECUTION_NOT_ALLOWED | Synchronous execution is not allowed for bulk operations with 1000 or more items. Please set forceSync to false or reduce the number of items below 1000. | |
400 | SYNC_EXECUTION_NOT_ALLOWED_FOR_BULK_UPDATE_CLIENTS | Synchronous execution is not allowed for bulk update clients with 1000 or more items. Please set forceSync to false or reduce the number of items below 1000. | |
400 | SYSTEM_DOES_NOT_SUPPORT_MORE_THAN_100000_CUSTOMERS | System does not support more than 100,000 customers | |
400 | UNEXPECTED_FIELD | Unexpected field: {field} | |
400 | UNLIMITED_COMMUNICATION_ALREADY_EXISTS | Unlimited communication already exists | |
400 | UNSUPPORTED_EVENT_TYPE: | Unsupported event type: {eventType} | |
400 | USE_OTHER_SERVICE_COMMUNICATION_DELETE | Use delete service to delete communication | |
400 | USER_ALREADY_EXISTS | User already exists | |
400 | VALIDATION_ERROR | Validation error! | |
400 | WALLET_IDENTIFIER_REQUIRED | Wallet identifier is required for pass template creation | |
400 | WALLET_NOT_CONFIGURED | Wallet is not configured with pass-builder. Please complete wallet migration first. | |
401 | PASSBUILDER_TOKEN_MISSING | PassBuilder token is missing | |
401 | UNAUTHORIZED | Unauthorized! | |
403 | FORBIDDEN | Forbidden! | |
404 | CERTIFICATE_NOT_FOUND | Certificate not found! | |
404 | CLASS_NOT_FOUND | Requested Google Wallet class not found. | |
404 | COUPON_TEMPLATE_NOT_FOUND | Coupon template not found | |
404 | CREATE_WALLET_CLASS_FAILED | Failed to create Google Wallet class. | |
404 | INITIALIZE_WALLET_OBJECT_CLIENT_FAILED | Failed to initialize Google Wallet client. | |
404 | MISSING_ANDROID_CLASS_ID | Missing Android class ID | |
404 | MISSING_FIELD | Missing field: {field} | |
404 | MODEL_NOT_FOUND | Model not found! | |
404 | OBJECT_CREATION_FAILED | Failed to create Google Wallet object. | |
404 | OBJECT_NOT_FOUND | Object not found | |
404 | OBJECT_UPDATE_FAILED | Failed to update Google Wallet object. | |
404 | PACK_NOT_ASSIGNED | No credit pack is assigned to this wallet. | |
404 | PASS_BUILDER_PASS_ID_NOT_FOUND | Pass builder pass ID not found | |
404 | PASS_NOT_FOUND | Pass not found | |
404 | PASSBUILDER_UPDATE_FAILED | Failed to update wallet with PassBuilder info | |
404 | PATH_NOT_FOUND | Path not found! | |
404 | STORECARD_NOT_FOUND | Storecard pass not found | |
404 | TEMPLATE_NOT_FOUND | Template not found : {templateName} | |
404 | TOKEN_MISMATCH_OR_DEVICE_NOT_FOUND | Token mismatch or device not found | |
404 | UNSUPPORTED_WALLET_TYPE | Unsupported wallet type | |
404 | UPDATE_OPERATION_NOT_SUPPORTED | Update operation not supported | |
404 | UPDATE_WALLET_CLASS_FAILED | Failed to update Google Wallet class. | |
404 | WALLET_NOT_FOUND | Wallet not found | |
404 | WALLET_UPDATE_FAILED | Failed to update wallet | |
409 | BARCODE_ALREADY_EXISTS | Barcode already exists | |
409 | CLIENT_ALREADY_EXISTS | Client already exists | |
409 | EMAIL_ALREADY_EXISTS | Email already exists | |
409 | INSUFFICIENT_CREDIT_PARTIAL | Some channels do not have enough credit to notify every client. Confirm to send only on the channels that do. | |
409 | OVERLAPPING_COMMUNICATIONS | Overlapping communications exist for the selected dates | |
409 | OVERLAPPING_DATES | Hotel is already reserved for the selected dates | |
409 | PACK_HAS_ASSIGNED_MANAGERS | Cannot delete pack: managers are still assigned to it | |
409 | PASSBUILDER_IDENTITY_INCOMPLETE | PassBuilder identity is incomplete or contradictory. Repair the wallet before continuing. | |
409 | PASSBUILDER_IDENTITY_PROVISIONING | PassBuilder identity provisioning is already in progress. Retry shortly. | |
409 | PUSH_NOTIFICATION_SCHEDULE_CONFLICT | A notification is already scheduled at this date and time. Please choose another time at least {seconds} seconds apart. | |
409 | STORE_CARD_ALREADY_EXISTS | This wallet already has a loyalty card | |
409 | TEMPLATE_ALREADY_EXISTS | Template already exists | |
415 | UNSUPPORTED_MEDIA_TYPE | Unsupported Content-Type. Use application/json or multipart/form-data. | |
500 | BATCH_OPERATION_FAILED | Batch operation failed: {error} | |
500 | GOOGLE_AUTH_INIT_FAILED | Failed to initialize Google Auth client. | |
500 | UNKNOWN_ERROR | Unknown error! | |
500 | WALLET_CLIENT_INIT_FAILED | Failed to initialize Google Wallet client. | |
500 | WALLET_UPDATE_ERROR | An error occurred while updating the wallet | |
502 | SMS_CREDIT_LOOKUP_FAILED | Failed to retrieve SMS credit information | |
502 | SMS_LOGIN_FAILED | Failed to authenticate with the SMS provider | |
502 | SMS_SEND_FAILED | Failed to send SMS through the provider | |
503 | PASS_BUILDER_ERROR | External service error |