> ## 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.

# Authentication

> Learn how to authenticate your API requests using HTTP Basic Auth

## Overview

The Modulus Labs QR API uses **HTTP Basic Authentication** to secure all API requests. You'll need your Secret Key, which will be provided by Modulus Labs.

<Warning>
  **Keep your Secret Key secure!** Do not share your authentication credentials in publicly accessible areas such as GitHub, client-side code, or any other public repositories.
</Warning>

## Your Secret Key

When you sign up, Modulus Labs will provide you with a **Secret Key** that looks like this:

```
sk_eaNv7t5xyCuiBfGCq2q7wu9uHEH3mTQ1Mq0c53XO1c53vfG
```

<Note>
  Secret Keys always start with the prefix `sk_` to help you identify them.
</Note>

## How Basic Authorization Works

HTTP Basic Auth requires a username and password. For the QR API:

* **Username**: Your Secret Key
* **Password**: Empty string (leave blank)

### Step-by-Step Process

<Steps>
  <Step title="Combine username and password">
    Combine your Secret Key with a colon (`:`) and an empty password

    ```
    sk_eaNv7t5xyCuiBfGCq2q7wu9uHEH3mTQ1Mq0c53XO1c53vfG:
    ```
  </Step>

  <Step title="Base64 encode">
    Apply Base64 encoding to the string from Step 1

    ```
    c2tfZWFOdjd0NXh5Q3VpQmZHQ3EycTd3dTl1SEVIM21UUTFNcTBjNTNYTzFjNTN2Zkc6
    ```
  </Step>

  <Step title="Add to header">
    Add the authorization header with "Basic" followed by the Base64 encoded string

    ```
    Authorization: Basic c2tfZWFOdjd0NXh5Q3VpQmZHQ3EycTd3dTl1SEVIM21UUTFNcTBjNTNYTzFjNTN2Zkc6
    ```
  </Step>
</Steps>

## Code Examples

Most HTTP clients handle Basic Auth automatically. Here's how to implement it in different languages:

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

  const secretKey = 'sk_eaNv7t5xyCuiBfGCq2q7wu9uHEH3mTQ1Mq0c53XO1c53vfG';

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

  ```python Python theme={null}
  import requests

  secret_key = 'sk_eaNv7t5xyCuiBfGCq2q7wu9uHEH3mTQ1Mq0c53XO1c53vfG'

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

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

  $secretKey = 'sk_eaNv7t5xyCuiBfGCq2q7wu9uHEH3mTQ1Mq0c53XO1c53vfG';

  $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' => $encryptedJWE]));
  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);
  curl_close($ch);
  ```

  ```java Java theme={null}
  import java.net.http.*;
  import java.util.Base64;

  String secretKey = "sk_eaNv7t5xyCuiBfGCq2q7wu9uHEH3mTQ1Mq0c53XO1c53vfG";
  String auth = secretKey + ":";
  String encodedAuth = Base64.getEncoder().encodeToString(auth.getBytes());

  HttpClient client = HttpClient.newHttpClient();
  HttpRequest request = HttpRequest.newBuilder()
      .uri(URI.create("https://qrph.sbx.moduluslabs.io/v1/pay/qr"))
      .header("Authorization", "Basic " + encodedAuth)
      .header("Content-Type", "application/json")
      .POST(HttpRequest.BodyPublishers.ofString(requestBody))
      .build();

  HttpResponse<String> response = client.send(request,
      HttpResponse.BodyHandlers.ofString());
  ```

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

  ```go Go theme={null}
  package main

  import (
  	"bytes"
  	"fmt"
  	"net/http"
  )

  func main() {
  	secretKey := "sk_eaNv7t5xyCuiBfGCq2q7wu9uHEH3mTQ1Mq0c53XO1c53vfG"

  	req, _ := http.NewRequest("POST",
  		"https://qrph.sbx.moduluslabs.io/v1/pay/qr",
  		bytes.NewBufferString(`{"Token": "eyJhbGciOiJBMjU2S1ciL..."}`))
  	req.SetBasicAuth(secretKey, "")
  	req.Header.Set("Content-Type", "application/json")

  	resp, err := (&http.Client{}).Do(req)
  	if err != nil {
  		fmt.Printf("Request failed: %v\n", err)
  		return
  	}
  	defer resp.Body.Close()

  	fmt.Printf("Status: %d\n", resp.StatusCode)
  }
  ```

  ```csharp C# / .NET theme={null}
  using System.Net.Http.Headers;
  using System.Text;

  var secretKey = "sk_eaNv7t5xyCuiBfGCq2q7wu9uHEH3mTQ1Mq0c53XO1c53vfG";

  using var client = new HttpClient();
  var authBytes = Encoding.ASCII.GetBytes($"{secretKey}:");
  client.DefaultRequestHeaders.Authorization =
      new AuthenticationHeaderValue("Basic", Convert.ToBase64String(authBytes));

  var content = new StringContent(
      "{\"Token\": \"eyJhbGciOiJBMjU2S1ciL...\"}",
      Encoding.UTF8,
      "application/json"
  );

  var response = await client.PostAsync(
      "https://qrph.sbx.moduluslabs.io/v1/pay/qr",
      content
  );

  var body = await response.Content.ReadAsStringAsync();
  Console.WriteLine($"Response: {body}");
  ```
</CodeGroup>

<Tip>
  Notice the colon (`:`) after the Secret Key in the cURL example. This indicates an empty password.
</Tip>

## Manual Base64 Encoding

If you need to manually encode the authorization header:

### Using Command Line

<CodeGroup>
  ```bash macOS/Linux theme={null}
  echo -n 'sk_eaNv7t5xyCuiBfGCq2q7wu9uHEH3mTQ1Mq0c53XO1c53vfG:' | base64
  ```

  ```powershell Windows PowerShell theme={null}
  [Convert]::ToBase64String([Text.Encoding]::UTF8.GetBytes("sk_eaNv7t5xyCuiBfGCq2q7wu9uHEH3mTQ1Mq0c53XO1c53vfG:"))
  ```
</CodeGroup>

### Using JavaScript

```javascript theme={null}
const secretKey = 'sk_eaNv7t5xyCuiBfGCq2q7wu9uHEH3mTQ1Mq0c53XO1c53vfG';
const credentials = Buffer.from(`${secretKey}:`).toString('base64');
const authHeader = `Basic ${credentials}`;
```

## Security Requirements

<CardGroup cols={2}>
  <Card title="HTTPS Only" icon="lock">
    All API requests **must** be made over HTTPS. Calls made over plain HTTP will fail.
  </Card>

  <Card title="Authentication Required" icon="shield-check">
    All API requests must include valid authentication credentials or they will fail.
  </Card>

  <Card title="Keep Keys Secure" icon="eye-slash">
    Never expose your Secret Key in client-side code or public repositories.
  </Card>

  <Card title="Rotate Keys" icon="rotate">
    Regularly rotate your keys and immediately revoke compromised ones.
  </Card>
</CardGroup>

## Authentication Errors

If authentication fails, you'll receive one of these error responses:

| Error Code | Description                    |
| ---------- | ------------------------------ |
| `10000003` | Account not found              |
| `10000006` | API Key not found              |
| `10000008` | API Key expired                |
| `10000009` | API Key revoked                |
| `10000010` | API Key suspended              |
| `10000011` | API Key deleted                |
| `10000012` | Unauthorized to perform action |
| `10000013` | Invalid API Key                |
| `10000015` | Insufficient permissions       |

### Example Error Response

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

<Note>
  See the [Errors](/docs/errors) page for a complete list of error codes and how to handle them.
</Note>

## Testing Your Authentication

Use the [Ping endpoint](/api-reference/qr/ping) to test your authentication:

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

If authentication is successful, you'll receive:

```
Pong!
```

## Best Practices

<AccordionGroup>
  <Accordion title="Use Environment Variables">
    Store your Secret Key in environment variables, never hardcode them in your source code.

    ```javascript theme={null}
    const secretKey = process.env.MODULUS_SECRET_KEY;
    ```
  </Accordion>

  <Accordion title="Implement Key Rotation">
    Regularly rotate your Secret Keys and maintain a grace period where both old and new keys work.
  </Accordion>

  <Accordion title="Use Different Keys for Environments">
    Use separate Secret Keys for sandbox and production environments to prevent accidental charges.
  </Accordion>

  <Accordion title="Monitor Authentication Failures">
    Track authentication failures in your logs to detect potential security issues.
  </Accordion>

  <Accordion title="Revoke Compromised Keys Immediately">
    If a Secret Key is compromised, contact Modulus Labs support immediately to revoke it.
  </Accordion>
</AccordionGroup>

## Next Steps

<CardGroup cols={2}>
  <Card title="Encryption Guide" icon="shield-halved" href="/docs/qr/encryption">
    Learn about JWE token encryption for request/response payloads
  </Card>

  <Card title="Create QR Code" icon="qrcode" href="/api-reference/qr/create">
    Make your first API call to create a Dynamic QR Ph
  </Card>
</CardGroup>
