Documentation Index Fetch the complete documentation index at: https://docs.linkxg.com/llms.txt
Use this file to discover all available pages before exploring further.
LinkXG uses standard HTTP status codes and consistent error response formats. This guide explains how errors are structured and how to handle them in your integration.
All error responses follow a consistent structure:
{
"success" : false ,
"error" : {
"code" : "ERROR_CODE" ,
"message" : "Human-readable description" ,
"details" : {}
}
}
Field Description successAlways false for errors error.codeMachine-readable error code error.messageHuman-readable description error.detailsAdditional context (optional)
HTTP status codes
Status Meaning When it occurs 400 Bad Request Invalid input, malformed JSON, missing required fields 401 Unauthorized Missing or invalid authentication token 403 Forbidden Valid token but insufficient permissions 404 Not Found Resource does not exist or is not accessible 409 Conflict Resource conflict (e.g., duplicate SKU) 422 Unprocessable Entity Validation failed 429 Too Many Requests Rate limit exceeded 500 Internal Server Error Server-side error 503 Service Unavailable Temporary unavailability
Common error codes
Authentication errors
Code Status Description INVALID_CREDENTIALS401 Email or password incorrect TOKEN_EXPIRED401 Access token has expired TOKEN_INVALID401 Token is malformed or revoked REFRESH_TOKEN_REUSED401 Refresh token has already been used INSUFFICIENT_SCOPE403 Token lacks required scope
Permission errors
Code Status Description INSUFFICIENT_PERMISSIONS403 User role cannot perform this action MISSING_CAPABILITY403 Subscription tier does not include this feature LIMIT_EXCEEDED403 Resource or rate limit reached TENANT_MISMATCH403 Attempting to access another tenant’s resources
Validation errors
Code Status Description VALIDATION_ERROR422 Input failed validation DUPLICATE_SKU409 SKU already exists in your portfolio INVALID_FORMAT400 Field format is incorrect REQUIRED_FIELD_MISSING400 Required field not provided
Resource errors
Code Status Description NOT_FOUND404 Resource does not exist ALREADY_EXISTS409 Resource already exists RESOURCE_LOCKED423 Resource is locked for editing
Validation error details
Validation errors include field-level details:
{
"success" : false ,
"error" : {
"code" : "VALIDATION_ERROR" ,
"message" : "Validation failed" ,
"details" : {
"fields" : [
{
"field" : "sku" ,
"message" : "SKU must be unique within your company" ,
"value" : "WIDGET-001"
},
{
"field" : "price" ,
"message" : "Price must be a positive number" ,
"value" : -10
}
]
}
}
}
Use the field value to highlight specific form fields or log the exact problem.
Handling errors in code
Basic error handling
async function createProduct ( productData ) {
const response = await fetch ( 'https://api.linkxg.com/api/v1/products' , {
method: 'POST' ,
headers: {
'Authorization' : `Bearer ${ accessToken } ` ,
'Content-Type' : 'application/json'
},
body: JSON . stringify ( productData )
});
if ( ! response . ok ) {
const error = await response . json ();
switch ( response . status ) {
case 401 :
// Token expired — refresh and retry
await refreshToken ();
return createProduct ( productData );
case 403 :
if ( error . error . code === 'MISSING_CAPABILITY' ) {
throw new Error ( 'This feature requires a plan upgrade' );
}
throw new Error ( 'Permission denied' );
case 409 :
if ( error . error . code === 'DUPLICATE_SKU' ) {
throw new Error ( `SKU ${ productData . sku } already exists` );
}
throw new Error ( 'Conflict' );
case 422 :
// Validation error — return field details
throw new ValidationError ( error . error . details . fields );
case 429 :
// Rate limited — wait and retry
const retryAfter = response . headers . get ( 'Retry-After' ) || 60 ;
await sleep ( retryAfter * 1000 );
return createProduct ( productData );
default :
throw new Error ( error . error . message );
}
}
return response . json ();
}
Retry logic for transient errors
Some errors are transient and can be retried:
Status Retry? Strategy 429 Yes Wait for Retry-After duration 500 Yes Exponential backoff, max 3 retries 503 Yes Exponential backoff, max 3 retries 401 Maybe Refresh token, then retry once 400, 403, 404, 409, 422 No These indicate a problem with the request
async function requestWithRetry ( url , options , maxRetries = 3 ) {
const retryableStatuses = [ 429 , 500 , 503 ];
let lastError ;
for ( let attempt = 0 ; attempt <= maxRetries ; attempt ++ ) {
try {
const response = await fetch ( url , options );
if ( response . ok ) {
return response . json ();
}
if ( ! retryableStatuses . includes ( response . status )) {
// Non-retryable error
throw await response . json ();
}
// Calculate backoff
const retryAfter = response . headers . get ( 'Retry-After' );
const delay = retryAfter
? parseInt ( retryAfter ) * 1000
: Math . min ( 1000 * Math . pow ( 2 , attempt ), 30000 );
await sleep ( delay );
} catch ( error ) {
lastError = error ;
}
}
throw lastError ;
}
Security considerations
Do not expose error details to end users. Internal error codes and stack traces should be logged, not displayed. Show generic messages to users.
404 for access denied. When a user requests a resource they cannot access (wrong tenant, insufficient permissions), the API returns 404 rather than 403 to avoid revealing that the resource exists.
Rate limit errors do not confirm existence. Rate limiting is applied before resource lookup, so a 429 does not indicate whether the requested resource exists.
Logging recommendations
Log the following for debugging:
Request URL and method
Response status code
Error code and message
Request ID (from X-Request-Id header)
Timestamp
Do not log:
Authentication tokens
Full request bodies containing sensitive data
User passwords or secrets
Next steps
Authentication Set up API authentication
API Reference Browse the complete API documentation