> ## Documentation Index
> Fetch the complete documentation index at: https://docs.moduluslabs.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Errors

> Understanding error codes and how to handle them

## Overview

The Modulus Labs QR API uses conventional HTTP response status codes to indicate the success or failure of API requests. Error responses include detailed information to help you quickly identify and resolve issues.

## HTTP Status Codes

<CardGroup cols={3}>
  <Card title="2xx Success" icon="circle-check" color="#10b981">
    Request completed successfully
  </Card>

  <Card title="4xx Client Error" icon="circle-exclamation" color="#f59e0b">
    Error in the request (missing parameters, validation failure, etc.)
  </Card>

  <Card title="5xx Server Error" icon="circle-xmark" color="#ef4444">
    Unexpected error on Modulus Labs' servers
  </Card>
</CardGroup>

### Status Code Ranges

| Status Code | Meaning      | What to Do                                    |
| ----------- | ------------ | --------------------------------------------- |
| **200-299** | Success      | Request worked as expected                    |
| **400-499** | Client Error | Check your request parameters and credentials |
| **500-599** | Server Error | Contact Modulus Labs support                  |

<Note>
  **5xx errors are rare** and shouldn't happen under normal circumstances. If you encounter persistent 5xx errors, please contact support immediately.
</Note>

## Error Response Format

The API returns a standard JSON error object:

```json theme={null}
{
  "code": "10000002",
  "error": "Account is disabled. Please contact support for assistance.",
  "referenceNumber": "338e2710-8268-4afe-8ef9-9765b0b74688"
}
```

### Error Object Properties

| Field             | Type   | Description                                                               |
| ----------------- | ------ | ------------------------------------------------------------------------- |
| `code`            | string | Machine-readable error code for programmatic handling                     |
| `error`           | string | Human-readable error message with details                                 |
| `referenceNumber` | string | Unique identifier for this error occurrence (use when contacting support) |

## Error Codes Reference

### Account & Authentication Errors (10000001-10000015)

<AccordionGroup>
  <Accordion title="10000001 - Account Locked" icon="lock">
    **Meaning:** Your account has been locked due to security concerns

    **Common Causes:**

    * Multiple failed authentication attempts
    * Suspicious activity detected
    * Manual lock by administrator

    **Solution:**

    * Contact Modulus Labs support to unlock your account
    * Provide the reference number from the error response
    * Review account security after unlocking

    ```json theme={null}
    {
      "code": "10000001",
      "error": "Account Locked",
      "referenceNumber": "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
    }
    ```
  </Accordion>

  <Accordion title="10000002 - Account Not Active" icon="ban">
    **Meaning:** Your account is not active or has been disabled

    **Common Causes:**

    * Account pending approval
    * Subscription expired
    * Account manually disabled

    **Solution:**

    * Check your email for activation instructions
    * Verify your subscription status
    * Contact support if the issue persists

    ```json theme={null}
    {
      "code": "10000002",
      "error": "Account is disabled. Please contact support for assistance.",
      "referenceNumber": "338e2710-8268-4afe-8ef9-9765b0b74688"
    }
    ```
  </Accordion>

  <Accordion title="10000003 - Account Not Found" icon="magnifying-glass">
    **Meaning:** The account associated with the credentials doesn't exist

    **Common Causes:**

    * Using credentials from deleted account
    * Typo in Secret Key
    * Wrong environment (sandbox vs. production)

    **Solution:**

    * Verify your Secret Key is correct
    * Ensure you're using the right environment
    * Contact support if you believe this is an error

    ```json theme={null}
    {
      "code": "10000003",
      "error": "Account not found",
      "referenceNumber": "b2c3d4e5-f6g7-8901-bcde-f12345678901"
    }
    ```
  </Accordion>

  <Accordion title="10000006 - API Key Not Found" icon="key">
    **Meaning:** The Secret Key provided doesn't exist in the system

    **Common Causes:**

    * Incorrect Secret Key
    * Key was deleted
    * Copy/paste error

    **Solution:**

    * Double-check your Secret Key
    * Generate a new key if needed
    * Verify key is properly stored in environment variables

    ```json theme={null}
    {
      "code": "10000006",
      "error": "API Key not found",
      "referenceNumber": "c3d4e5f6-g7h8-9012-cdef-123456789012"
    }
    ```
  </Accordion>

  <Accordion title="10000008 - API Key Expired" icon="clock">
    **Meaning:** Your Secret Key has expired

    **Common Causes:**

    * Key exceeded its validity period
    * Automatic expiration policy

    **Solution:**

    * Generate a new Secret Key
    * Update your application configuration
    * Implement key rotation strategy

    ```json theme={null}
    {
      "code": "10000008",
      "error": "API Key expired",
      "referenceNumber": "d4e5f6g7-h8i9-0123-defg-234567890123"
    }
    ```
  </Accordion>

  <Accordion title="10000009 - API Key Revoked" icon="circle-xmark">
    **Meaning:** Your Secret Key has been revoked

    **Common Causes:**

    * Key compromised and manually revoked
    * Revoked during key rotation
    * Security incident

    **Solution:**

    * Generate a new Secret Key immediately
    * Review security logs
    * Contact support if unexpected

    ```json theme={null}
    {
      "code": "10000009",
      "error": "API Key revoked",
      "referenceNumber": "e5f6g7h8-i9j0-1234-efgh-345678901234"
    }
    ```
  </Accordion>

  <Accordion title="10000010 - API Key Suspended" icon="pause">
    **Meaning:** Your Secret Key is temporarily suspended

    **Common Causes:**

    * Suspicious activity
    * Policy violation
    * Payment issue

    **Solution:**

    * Contact support to resolve the suspension
    * Provide reference number
    * Address the underlying issue

    ```json theme={null}
    {
      "code": "10000010",
      "error": "API Key suspended",
      "referenceNumber": "f6g7h8i9-j0k1-2345-fghi-456789012345"
    }
    ```
  </Accordion>

  <Accordion title="10000011 - API Key Deleted" icon="trash">
    **Meaning:** The Secret Key has been permanently deleted

    **Common Causes:**

    * Manual deletion
    * Account cleanup
    * Security incident response

    **Solution:**

    * Generate a new Secret Key
    * Update application configuration
    * Cannot recover deleted keys

    ```json theme={null}
    {
      "code": "10000011",
      "error": "API Key deleted",
      "referenceNumber": "g7h8i9j0-k1l2-3456-ghij-567890123456"
    }
    ```
  </Accordion>

  <Accordion title="10000012 - Unauthorized Action" icon="shield-xmark">
    **Meaning:** Not authorized to perform this action

    **Common Causes:**

    * Insufficient account permissions
    * API endpoint not available for your account type
    * Incorrect credentials

    **Solution:**

    * Verify your account has the required permissions
    * Check if you're using the correct endpoint
    * Contact support to upgrade permissions

    ```json theme={null}
    {
      "code": "10000012",
      "error": "Unauthorized to perform action",
      "referenceNumber": "h8i9j0k1-l2m3-4567-hijk-678901234567"
    }
    ```
  </Accordion>

  <Accordion title="10000013 - Invalid API Key" icon="key-slash">
    **Meaning:** The Secret Key format is invalid

    **Common Causes:**

    * Malformed key string
    * Incorrect encoding
    * Corrupted key during storage/retrieval

    **Solution:**

    * Verify the Secret Key format
    * Ensure no extra spaces or characters
    * Re-copy the key from secure storage

    ```json theme={null}
    {
      "code": "10000013",
      "error": "Invalid API Key",
      "referenceNumber": "i9j0k1l2-m3n4-5678-ijkl-789012345678"
    }
    ```
  </Accordion>

  <Accordion title="10000015 - Insufficient Permissions" icon="lock-keyhole">
    **Meaning:** API key doesn't have required permissions for this operation

    **Common Causes:**

    * Read-only key used for write operation
    * Key lacks specific permission
    * Permission not assigned to account

    **Solution:**

    * Use an API key with appropriate permissions
    * Request permission upgrade from support
    * Review key permissions in dashboard

    ```json theme={null}
    {
      "code": "10000015",
      "error": "Insufficient permissions",
      "referenceNumber": "j0k1l2m3-n4o5-6789-jklm-890123456789"
    }
    ```
  </Accordion>
</AccordionGroup>

## Error Response Types

The API returns errors in different formats depending on the authentication status:

<Tabs>
  <Tab title="Authenticated Errors">
    ### Declined Requests (Authenticated)

    When authenticated but the request is declined, errors are returned as **encrypted JWE tokens**:

    ```json theme={null}
    {
      "Token": "eyJhbGciOiJBMjU2S1ciLCJlbmMiOiJBMjU2Q0JDLUhTNTEyIn0..."
    }
    ```

    **After decryption:**

    ```json theme={null}
    {
      "code": "10000015",
      "error": "Insufficient permissions",
      "referenceNumber": "abc123-def456-ghi789"
    }
    ```

    <Info>
      You must decrypt these responses using your Encryption Key. See the [Encryption Guide](/docs/qr/encryption) for details.
    </Info>
  </Tab>

  <Tab title="Unauthenticated Errors">
    ### Unauthorized Requests (Not Authenticated)

    When authentication fails, errors are returned **unencrypted** as plain JSON:

    ```json theme={null}
    {
      "code": "10000013",
      "error": "Invalid API Key",
      "referenceNumber": "338e2710-8268-4afe-8ef9-9765b0b74688"
    }
    ```

    <Warning>
      Authentication errors bypass encryption since the credentials are invalid. Handle these separately in your code.
    </Warning>
  </Tab>
</Tabs>

## Handling Errors in Code

Here's how to properly handle errors in your application:

<CodeGroup>
  ```javascript Node.js theme={null}
  const axios = require('axios');
  const jose = require('jose');

  async function handleApiCall() {
    try {
      const response = await axios.post(
        'https://qrph.sbx.moduluslabs.io/v1/pay/qr',
        { Token: encryptedPayload },
        {
          auth: { username: secretKey, password: '' },
          headers: { 'Content-Type': 'application/json' }
        }
      );

      // Check if response contains Token (encrypted)
      if (response.data.Token) {
        const { plaintext } = await jose.compactDecrypt(
          response.data.Token,
          encryptionKey
        );
        const data = JSON.parse(new TextDecoder().decode(plaintext));

        // Check if decrypted data is an error
        if (data.code) {
          console.error(`Error ${data.code}: ${data.error}`);
          console.error(`Reference: ${data.referenceNumber}`);
          return null;
        }

        return data;
      }

      return response.data;

    } catch (error) {
      if (error.response) {
        // HTTP error response
        const { status, data } = error.response;

        if (data.code) {
          // Unencrypted error (authentication failure)
          console.error(`Auth Error ${data.code}: ${data.error}`);
          console.error(`Reference: ${data.referenceNumber}`);
        } else {
          console.error(`HTTP ${status}: ${JSON.stringify(data)}`);
        }
      } else {
        // Network or other error
        console.error('Request failed:', error.message);
      }
      throw error;
    }
  }
  ```

  ```python Python theme={null}
  import requests
  from jose import jwe
  import json

  def handle_api_call():
      try:
          response = requests.post(
              'https://qrph.sbx.moduluslabs.io/v1/pay/qr',
              json={'Token': encrypted_payload},
              auth=(secret_key, ''),
              headers={'Content-Type': 'application/json'}
          )

          # Raise exception for HTTP errors
          response.raise_for_status()

          data = response.json()

          # Check if response contains Token (encrypted)
          if 'Token' in data:
              decrypted = jwe.decrypt(data['Token'], encryption_key)
              payload = json.loads(decrypted)

              # Check if decrypted data is an error
              if 'code' in payload:
                  print(f"Error {payload['code']}: {payload['error']}")
                  print(f"Reference: {payload['referenceNumber']}")
                  return None

              return payload

          return data

      except requests.exceptions.HTTPError as e:
          # HTTP error response
          if e.response.status_code in [401, 403]:
              error_data = e.response.json()
              print(f"Auth Error {error_data['code']}: {error_data['error']}")
              print(f"Reference: {error_data['referenceNumber']}")
          else:
              print(f"HTTP {e.response.status_code}: {e.response.text}")
          raise

      except requests.exceptions.RequestException as e:
          # Network or other error
          print(f"Request failed: {str(e)}")
          raise
  ```

  ```php PHP theme={null}
  <?php

  function handleApiCall($encryptedPayload, $secretKey, $encryptionKey) {
      try {
          $ch = curl_init('https://qrph.sbx.moduluslabs.io/v1/pay/qr');
          curl_setopt($ch, CURLOPT_POST, 1);
          curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode(['Token' => $encryptedPayload]));
          curl_setopt($ch, CURLOPT_USERPWD, $secretKey . ':');
          curl_setopt($ch, CURLOPT_HTTPHEADER, ['Content-Type: application/json']);
          curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);

          $response = curl_exec($ch);
          $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
          curl_close($ch);

          $data = json_decode($response, true);

          // Check for HTTP errors
          if ($httpCode >= 400) {
              if (isset($data['code'])) {
                  error_log("Error {$data['code']}: {$data['error']}");
                  error_log("Reference: {$data['referenceNumber']}");
              }
              return null;
          }

          // Check if response contains Token (encrypted)
          if (isset($data['Token'])) {
              $decrypted = decryptJWE($data['Token'], $encryptionKey);
              $payload = json_decode($decrypted, true);

              // Check if decrypted data is an error
              if (isset($payload['code'])) {
                  error_log("Error {$payload['code']}: {$payload['error']}");
                  error_log("Reference: {$payload['referenceNumber']}");
                  return null;
              }

              return $payload;
          }

          return $data;

      } catch (Exception $e) {
          error_log("Request failed: " . $e->getMessage());
          throw $e;
      }
  }
  ```
</CodeGroup>

## Best Practices

<CardGroup cols={2}>
  <Card title="Log Reference Numbers" icon="file-lines">
    Always log the `referenceNumber` - it's essential for troubleshooting with support
  </Card>

  <Card title="Implement Retry Logic" icon="arrows-rotate">
    Implement exponential backoff for 5xx errors and rate limit errors
  </Card>

  <Card title="Handle Both Formats" icon="code-branch">
    Check for both encrypted and unencrypted error responses
  </Card>

  <Card title="Monitor Error Rates" icon="chart-line">
    Track error rates to identify integration issues early
  </Card>

  <Card title="Graceful Degradation" icon="shield-check">
    Provide fallback options when API calls fail
  </Card>

  <Card title="User-Friendly Messages" icon="message">
    Translate technical errors into user-friendly messages
  </Card>
</CardGroup>

## Testing Errors

You can simulate errors in the sandbox environment to test your error handling:

### Test with Invalid Credentials

```bash theme={null}
curl https://qrph.sbx.moduluslabs.io/ping \
  -u invalid_key:

# Response:
# {
#   "code": "10000006",
#   "error": "API Key not found",
#   "referenceNumber": "..."
# }
```

### Test with Malformed Request

```bash theme={null}
curl https://qrph.sbx.moduluslabs.io/v1/pay/qr \
  -u sk_valid_key: \
  -H "Content-Type: application/json" \
  -d '{"Token": "invalid_jwe_token"}'
```

## Getting Help

<Steps>
  <Step title="Check This Documentation">
    Review the error code and common solutions above
  </Step>

  <Step title="Test in Sandbox">
    Reproduce the error in the sandbox environment
  </Step>

  <Step title="Gather Information">
    Collect:

    * Error code
    * Reference number
    * Full request/response (remove sensitive data)
    * Timestamp
  </Step>

  <Step title="Contact Support">
    Email [support@moduluslabs.io](mailto:support@moduluslabs.io) with the gathered information
  </Step>
</Steps>

<Note>
  **Reference numbers are crucial** - always include them when contacting support for faster resolution.
</Note>

## Next Steps

<CardGroup cols={2}>
  <Card title="Testing Guide" icon="flask" href="/docs/qr/testing">
    Learn how to test error scenarios in sandbox
  </Card>

  <Card title="Quickstart" icon="rocket" href="/docs/qr/quickstart">
    Build a complete integration with proper error handling
  </Card>
</CardGroup>
