Skip to main content

Error Codes

This page documents all error codes returned by the Optropic API, along with their meanings and recommended actions.

Error Response Format

All errors follow this structure:

{
"error": {
"code": "ERROR_CODE",
"message": "Human-readable error description",
"details": {
// Additional context (optional)
}
},
"meta": {
"requestId": "req_abc123",
"timestamp": "2026-02-18T10:30:00Z"
}
}

Authentication Errors (401)

CodeMessageAction
MISSING_API_KEYNo API key providedAdd x-api-key header
INVALID_API_KEYAPI key is invalid or malformedCheck key format, create new key
EXPIRED_API_KEYAPI key has expiredCreate a new API key
REVOKED_API_KEYAPI key was revokedCreate a new API key

Example

{
"error": {
"code": "INVALID_API_KEY",
"message": "The provided API key is invalid or does not exist"
}
}

Validation Errors (400)

CodeMessageAction
INVALID_GTINGTIN is not validProvide 14-digit GTIN
INVALID_SERIALSerial number is invalidCheck serial format
INVALID_URLURL is malformedProvide valid GS1 Digital Link URL
MISSING_SIGNATURENo signature in URLInclude sig parameter
INVALID_SIGNATURE_FORMATSignature is malformedCheck signature encoding
MISSING_REQUIRED_FIELDRequired field missingInclude all required fields
INVALID_JSONRequest body is not valid JSONFix JSON syntax

Example

{
"error": {
"code": "INVALID_GTIN",
"message": "GTIN must be exactly 14 digits",
"details": {
"field": "gtin",
"provided": "1234567890",
"expected": "14 digits, numeric only"
}
}
}

Resource Errors (404, 409)

CodeHTTPMessageAction
KEY_NOT_FOUND404Signing key not foundRegister the key first
CODE_NOT_FOUND404Code not foundCheck serial/GTIN
DUPLICATE_SERIAL409Serial already existsUse unique serial
DUPLICATE_KEY409Public key already registeredKey already exists

Example

{
"error": {
"code": "DUPLICATE_SERIAL",
"message": "A code with this GTIN and serial already exists",
"details": {
"gtin": "04260799580008",
"serial": "SN-001",
"existingCodeId": "code_abc123"
}
}
}

Rate Limit Errors (429)

CodeMessageAction
RATE_LIMITEDToo many requestsWait and retry with backoff
DAILY_LIMIT_EXCEEDEDDaily quota exhaustedWait until midnight UTC
BURST_LIMIT_EXCEEDEDToo many requests per secondSlow down request rate

Example

{
"error": {
"code": "RATE_LIMITED",
"message": "Rate limit exceeded. Retry after 3600 seconds.",
"details": {
"limit": 1000,
"window": "daily",
"remaining": 0,
"retryAfter": 3600
}
}
}

Verification Errors

These aren't HTTP errors, but verification-specific results:

CodeVerdictMeaning
SIGNATURE_INVALIDCOUNTERFEITCryptographic signature doesn't match
KEY_REVOKEDSUSPICIOUSSigning key was revoked
EXCESSIVE_SCANSSUSPICIOUSUnusually high scan count
GEOGRAPHIC_ANOMALYSUSPICIOUSImpossible location pattern

Example

{
"verdict": "COUNTERFEIT",
"confidence": 0.0,
"checks": {
"signature": {
"passed": false,
"error": "SIGNATURE_INVALID",
"message": "Signature does not match any registered key"
}
}
}

Server Errors (500)

CodeMessageAction
INTERNAL_ERRORInternal server errorRetry; contact support if persistent
DATABASE_ERRORDatabase unavailableRetry after a few seconds
SIGNING_ERRORCode signing failedRetry; contact support if persistent

Example

{
"error": {
"code": "INTERNAL_ERROR",
"message": "An unexpected error occurred. Please try again.",
"details": {
"requestId": "req_abc123"
}
}
}
Include Request ID in Support Tickets

When contacting support, always include the requestId from the error response. This helps us trace the issue.

Error Handling Best Practices

1. Check HTTP Status First

const response = await fetch(url, options);

if (!response.ok) {
const error = await response.json();

switch (response.status) {
case 401:
// Handle authentication error
refreshApiKey();
break;
case 429:
// Handle rate limit
await sleep(error.error.details.retryAfter * 1000);
break;
case 400:
// Handle validation error
console.error('Invalid request:', error.error.message);
break;
default:
// Log and retry
console.error('API error:', error);
}
}

2. Log Errors with Context

function logError(error, context) {
console.error({
code: error.error?.code,
message: error.error?.message,
requestId: error.meta?.requestId,
context,
timestamp: new Date().toISOString(),
});
}

3. Display User-Friendly Messages

Map error codes to user-friendly messages:

const userMessages = {
INVALID_GTIN: 'Please enter a valid 14-digit product code.',
RATE_LIMITED: 'Too many requests. Please wait a moment and try again.',
SIGNATURE_INVALID: 'This product could not be verified as authentic.',
};

function getUserMessage(errorCode) {
return userMessages[errorCode] || 'An error occurred. Please try again.';
}