QrioTagQrioTag Docs
Help & Troubleshooting

Error Codes Reference

A complete reference of every error code returned by the QrioTag API, what each means, and how to resolve it.

How to use this reference

Every error response includes a code field (machine-readable, use in your code), a message field (human-readable, show to users), and an optional details field with additional context such as per-field validation errors. Find your error code below to understand its cause and how to resolve it.

Every error response from the QrioTag API follows this format:

{
  "success": false,
  "error": {
    "code": "ERROR_CODE",
    "message": "Human-readable description of what went wrong",
    "details": {}
  }
}

The code field is a machine-readable string you can use in your code. The message field is a human-readable explanation. The optional details field contains additional context (for example, field-level validation errors).

Error Codes

VALIDATION_ERROR

HTTP Status400 Bad Request
MeaningThe request body or query parameters failed validation.

Example response:

{
  "success": false,
  "error": {
    "code": "VALIDATION_ERROR",
    "message": "Invalid input data",
    "details": {
      "email": ["Invalid email format"],
      "password": ["Must be at least 8 characters"]
    }
  }
}

What to do:

  • Check the details field for which specific fields failed validation
  • Fix the input data and retry the request
  • Refer to the API Reference for the expected format of each field

NOT_FOUND

HTTP Status404 Not Found
MeaningThe requested resource does not exist, or you do not have access to it.

Example response:

{
  "success": false,
  "error": {
    "code": "NOT_FOUND",
    "message": "Tag with id 'tag_uuid_123' not found"
  }
}

What to do:

  • Verify the resource ID is correct
  • Check that the resource belongs to your account (tags owned by other users return NOT_FOUND, not FORBIDDEN, to prevent enumeration)
  • For scan endpoints: verify the encrypted ID is correct and the encryption key matches

UNAUTHORIZED

HTTP Status401 Unauthorized
MeaningThe request requires authentication but no valid token was provided.

Example response:

{
  "success": false,
  "error": {
    "code": "UNAUTHORIZED",
    "message": "Authentication required"
  }
}

What to do:

  • Include an Authorization: Bearer <token> header
  • Check that the token is an access token, not a refresh token
  • If the access token has expired, use the refresh token to get a new one: POST /api/v1/auth/refresh
  • If the refresh token has also expired, log in again

FORBIDDEN

HTTP Status403 Forbidden
MeaningYou are authenticated but do not have permission for this action.

Example response:

{
  "success": false,
  "error": {
    "code": "FORBIDDEN",
    "message": "Access denied"
  }
}

What to do:

  • Check that your account has the required role (some endpoints require ADMIN or SUPER_ADMIN)
  • Check that you own the resource you are trying to modify
  • For 2FA: if the error message is "Two-factor authentication required," include the twoFactorCode field in your login request

CONFLICT

HTTP Status409 Conflict
MeaningThe action conflicts with an existing resource.

Example response:

{
  "success": false,
  "error": {
    "code": "CONFLICT",
    "message": "A user with this email already exists"
  }
}

What to do:

  • For registration: use a different email address, or use the forgot password flow if you already have an account
  • For tag activation: the tag may already be activated by another user
  • For transfers: a pending transfer may already exist for this tag

RATE_LIMIT

HTTP Status429 Too Many Requests
MeaningYou have sent too many requests in a short period.

Example response:

{
  "success": false,
  "error": {
    "code": "RATE_LIMIT",
    "message": "Too many requests"
  }
}

What to do:

  • Check the Retry-After response header for how many seconds to wait
  • Implement exponential backoff in your client
  • If you are hitting rate limits frequently, consider upgrading to a higher subscription tier for higher limits
  • In development, restart the API server to reset rate limit counters

Rate limit reference:

EndpointLimit
Registration5/hour per IP
Password reset3/hour per IP
Scan30/minute per IP
Emergency scan5/minute per IP
Products listing30/minute per IP

TAG_CLONE_DETECTED

HTTP Status403 Forbidden
MeaningThe system detected a potential tag cloning attempt.

Example response:

{
  "success": false,
  "error": {
    "code": "TAG_CLONE_DETECTED",
    "message": "Tag verification failed - possible clone detected"
  }
}

What to do:

  • This error occurs when the same tag is scanned from two geographically impossible locations in a short time frame (for example, scanned in New York and London within 5 minutes)
  • If you are the tag owner and this is a false positive, contact support
  • If you are seeing this during development, it may be caused by VPN or proxy usage that changes your apparent location between requests

INVALID_TRANSITION

HTTP Status400 Bad Request
MeaningThe requested tag status change is not allowed.

Example response:

{
  "success": false,
  "error": {
    "code": "INVALID_TRANSITION",
    "message": "Invalid status transition from 'DEACTIVATED' to 'LOST'"
  }
}

What to do:

  • Check the Tag Lifecycle page for the full list of valid transitions
  • Common mistake: trying to set a LOST tag to DEACTIVATED directly (change it to ACTIVE first)
  • Common mistake: trying to mark a PENDING_SETUP tag as LOST (complete the profile to reach ACTIVE first)

Valid transitions reference:

FromAllowed To
PENDING_SETUPACTIVE
ACTIVELOST, STOLEN, DEACTIVATED
LOSTFOUND, ACTIVE, STOLEN
FOUNDACTIVE
STOLENACTIVE, DEACTIVATED
DEACTIVATEDACTIVE
EXPIREDACTIVE (after PRO upgrade)

INTERNAL_ERROR

HTTP Status500 Internal Server Error
MeaningSomething went wrong on the server.

Example response:

{
  "success": false,
  "error": {
    "code": "INTERNAL_ERROR",
    "message": "An unexpected error occurred"
  }
}

What to do:

  • This is a server-side bug. Retry the request after a few seconds.
  • If the error persists, check the API server logs for a stack trace
  • In development, the error message may include more details about the cause
  • Report persistent 500 errors as bugs

Error Handling Best Practices

In your client code

async function apiCall(url: string, options?: RequestInit) {
  const response = await fetch(url, options);
  const data = await response.json();

  if (!data.success) {
    switch (data.error.code) {
      case 'UNAUTHORIZED':
        // Redirect to login or refresh token
        break;
      case 'RATE_LIMIT':
        // Wait and retry
        const retryAfter = response.headers.get('Retry-After');
        break;
      case 'VALIDATION_ERROR':
        // Show field-level errors to the user
        break;
      default:
        // Show generic error message
        break;
    }
  }

  return data;
}

Key principles

  1. Always check the success field in the response
  2. Use the code field for programmatic error handling (not the message)
  3. Show the message field to users — it is human-readable
  4. For VALIDATION_ERROR, iterate over details to show per-field errors
  5. Implement automatic token refresh on 401 responses
  6. Implement retry with backoff on 429 responses

Was this page helpful?

Error Codes Reference | QrioTag Docs