> For the complete documentation index, see [llms.txt](https://docs.docs-dispatcher.io/docs-dispatcher/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.docs-dispatcher.io/docs-dispatcher/authentication/basic-auth.md).

# Authentication overview

Docs-Dispatcher accepts two authentication schemes on every API request. Pick the one that fits your integration — both reach the same endpoints with the same permissions.

| Method                                                                      | When to use                                                            | Lifetime               |
| --------------------------------------------------------------------------- | ---------------------------------------------------------------------- | ---------------------- |
| [**Basic Auth**](/docs-dispatcher/authentication/basic-auth.md) (this page) | Server-to-server, stable account credentials                           | Never expires          |
| [**JWT Bearer**](/docs-dispatcher/authentication/jwt-bearer.md)             | Short-lived sessions, browser-mediated logins (proxied), impersonation | \~120 min, refreshable |

This page covers Basic Auth. For the token flow, see [JWT Bearer authentication](/docs-dispatcher/authentication/jwt-bearer.md).

## Basic Auth in one line

Every Basic Auth request carries this header:

```http
Authorization: Basic <base64(email:password)>
```

That's it — no token to fetch, no refresh flow, no session to manage.

## Overview

Docs-Dispatcher uses **HTTP Basic Authentication** for all API requests. This is a simple and secure method where you send your credentials with each request.

**Authentication Flow:**

```
1. Encode your email:password as base64
2. Add Authorization: Basic <base64> header to each request
3. Make Dispatcher API requests
```

```mermaid
graph LR
    A[Your App] -->|Basic Auth Header| B[Dispatcher API]
    B -->|Service Response| A
```

## Basic Authentication Header

### Header Format

All API requests must include the `Authorization` header with Basic authentication:

```http
Authorization: Basic <base64(email:password)>
```

### How to Create the Header

1. **Concatenate** your email and password with a colon: `email:password`
2. **Encode** the string as base64
3. **Prefix** with `Basic`

**Example:**

```
Email: olivier.roelants@gmail.com
Password: your-password

String to encode: olivier.roelants@gmail.com:your-password
Base64 encoded: b2xpdmllci5yb2VsYW50c0BnbWFpbC5jb206eW91ci1wYXNzd29yZA==

Header: Authorization: Basic b2xpdmllci5yb2VsYW50c0BnbWFpbC5jb206eW91ci1wYXNzd29yZA==
```

### Response (Success)

When credentials are valid, the API responds with the requested data (200 OK).

### Response (Error)

**Invalid Credentials (401):**

```json
{
  "error": "unauthorized",
  "message": "Invalid email or password"
}
```

**Missing Authorization Header (401):**

```json
{
  "error": "unauthorized",
  "message": "Authorization header required"
}
```

## Code Examples

### curl

```bash
# Method 1: Let curl handle Basic Auth encoding
curl -X POST https://api.docs-dispatcher.io/api/invoicing \
  -u "your-email@company.com:your-password" \
  -H "Content-Type: application/json" \
  -d @request.json

# Method 2: Manually encode and set header
EMAIL="your-email@company.com"
PASSWORD="your-password"
AUTH_HEADER=$(echo -n "$EMAIL:$PASSWORD" | base64)

curl -X POST https://api.docs-dispatcher.io/api/invoicing \
  -H "Authorization: Basic $AUTH_HEADER" \
  -H "Content-Type: application/json" \
  -d @request.json
```

### Node.js (fetch)

```javascript
// Create Basic Auth header
function createBasicAuthHeader(email, password) {
  const credentials = `${email}:${password}`;
  const base64Credentials = Buffer.from(credentials).toString('base64');
  return `Basic ${base64Credentials}`;
}

// Use in requests
const email = 'your-email@company.com';
const password = 'your-password';
const authHeader = createBasicAuthHeader(email, password);

const response = await fetch('https://api.docs-dispatcher.io/api/invoicing', {
  method: 'POST',
  headers: {
    'Authorization': authHeader,
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    providerName: 'qonto',
    documentType: 'INVOICE',
    template: { /* ... */ }
  })
});

if (!response.ok) {
  throw new Error(`Request failed: ${response.status}`);
}

const result = await response.json();
```

### PHP (Guzzle)

```php
<?php
require 'vendor/autoload.php';

use GuzzleHttp\Client;

$email = 'your-email@company.com';
$password = 'your-password';

$client = new Client();

try {
    $response = $client->post('https://api.docs-dispatcher.io/api/invoicing', [
        'auth' => [$email, $password],  // Guzzle handles Basic Auth encoding
        'json' => [
            'providerName' => 'qonto',
            'documentType' => 'INVOICE',
            'template' => [ /* ... */ ]
        ]
    ]);

    $result = json_decode($response->getBody(), true);
    print_r($result);

} catch (\GuzzleHttp\Exception\ClientException $e) {
    $error = json_decode($e->getResponse()->getBody(), true);
    echo "Request failed: " . $error['message'];
}
```

### Java (HttpClient)

```java
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.util.Base64;

public class DispatcherClient {
    private final String authHeader;
    private final HttpClient client;

    public DispatcherClient(String email, String password) {
        String credentials = email + ":" + password;
        String base64Credentials = Base64.getEncoder()
            .encodeToString(credentials.getBytes());
        this.authHeader = "Basic " + base64Credentials;
        this.client = HttpClient.newHttpClient();
    }

    public String dispatchInvoice(String requestJson) throws Exception {
        HttpRequest request = HttpRequest.newBuilder()
            .uri(URI.create("https://api.docs-dispatcher.io/api/invoicing"))
            .header("Authorization", authHeader)
            .header("Content-Type", "application/json")
            .POST(HttpRequest.BodyPublishers.ofString(requestJson))
            .build();

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

        if (response.statusCode() != 200) {
            throw new Exception("Request failed: " + response.body());
        }

        return response.body();
    }
}
```

## Encoding Base64

### Command Line (bash)

```bash
# Linux/Mac
echo -n "email@company.com:password" | base64

# Output: ZW1haWxAY29tcGFueS5jb206cGFzc3dvcmQ=
```

### Node.js

```javascript
const credentials = 'email@company.com:password';
const base64 = Buffer.from(credentials).toString('base64');
console.log(base64);
// Output: ZW1haWxAY29tcGFueS5jb206cGFzc3dvcmQ=
```

### PHP

```php
<?php
$credentials = 'email@company.com:password';
$base64 = base64_encode($credentials);
echo $base64;
// Output: ZW1haWxAY29tcGFueS5jb206cGFzc3dvcmQ=
```

### Java

```java
import java.util.Base64;

String credentials = "email@company.com:password";
String base64 = Base64.getEncoder().encodeToString(credentials.getBytes());
System.out.println(base64);
// Output: ZW1haWxAY29tcGFueS5jb206cGFzc3dvcmQ=
```

{% hint style="info" %}
**No Token Expiration:** Unlike JWT tokens, Basic Auth credentials don't expire. You send them with every request. This simplifies authentication but requires secure credential storage.
{% endhint %}

## Security Best Practices

### 1. Never Hardcode Credentials

❌ **Bad:**

```javascript
const email = 'user@company.com';
const password = 'mysecretpassword'; // NEVER do this
```

✅ **Good:**

```javascript
const email = process.env.DOCS_DISPATCHER_EMAIL;
const password = process.env.DOCS_DISPATCHER_PASSWORD;
```

### 2. Store Credentials Securely

**Backend (Node.js/Java/PHP):**

* Environment variables
* Encrypted configuration files
* Secret management services (AWS Secrets Manager, HashiCorp Vault, Azure Key Vault)

**Browser:**

* ❌ **Never store credentials in localStorage/sessionStorage**
* ❌ **Never expose credentials to browser JavaScript**
* ✅ **Use backend proxy** for all Dispatcher calls

**Example secure pattern:**

```
Browser → Your Backend API → Dispatcher API
         (no credentials)    (with Basic Auth)
```

### 3. Use HTTPS Only

All API requests **must** use HTTPS. HTTP requests will be rejected.

```javascript
// ❌ NEVER use HTTP
const url = 'http://api.docs-dispatcher.io/...';

// ✅ Always use HTTPS
const url = 'https://api.docs-dispatcher.io/...';
```

### 4. Rotate Credentials Regularly

* Change passwords every 90 days
* Revoke unused API access
* Audit user access periodically
* Use strong, unique passwords (min 12 characters)

### 5. Handle Authentication Errors

Always check for 401 responses:

```javascript
async function dispatchWithAuth(endpoint, data, email, password) {
  const authHeader = createBasicAuthHeader(email, password);

  const response = await fetch(endpoint, {
    method: 'POST',
    headers: {
      'Authorization': authHeader,
      'Content-Type': 'application/json'
    },
    body: JSON.stringify(data)
  });

  if (response.status === 401) {
    throw new Error('Invalid credentials');
  }

  if (!response.ok) {
    throw new Error(`HTTP ${response.status}: ${await response.text()}`);
  }

  return response.json();
}
```

## Common Authentication Errors

### 401 Unauthorized

**Causes:**

* Wrong email or password
* Missing Authorization header
* Incorrectly formatted Basic Auth header

**Solutions:**

* Verify credentials are correct
* Check header format: `Authorization: Basic <base64>`
* Ensure credentials are properly base64 encoded
* Test credentials with `-u` flag in curl

**Debug example:**

```bash
# Test your credentials
curl -X GET https://api.docs-dispatcher.io/healthz \
  -u "your-email@company.com:your-password"

# If valid: 200 OK
# If invalid: 401 Unauthorized
```

### 403 Forbidden

**Causes:**

* User lacks permissions for the requested service
* IP whitelist restriction

**Solutions:**

* Contact admin to grant necessary permissions
* Verify IP is whitelisted (if IP restrictions enabled)

### 429 Rate Limit

**Causes:**

* Too many requests (>100/minute per user)

**Solutions:**

* Add rate limiting to your application
* Implement exponential backoff for retries
* Cache results when possible

## Next Steps

Now that you understand Basic Authentication:

1. [**Use Basic Auth with Dispatcher**](/docs-dispatcher/authentication/using-basic-auth.md) - Complete authentication guide
2. [**Quickstart Guide**](/docs-dispatcher/start-here/quickstart.md) - Send an invoice using validation endpoint
3. [**Invoice Recipe**](/docs-dispatcher/how-to-recipes/invoice.md) - Generate and dispatch a real invoice

## Support

* Authentication issues: <support@docs-dispatcher.io>
* Password reset: Contact support
* Account access: <support@docs-dispatcher.io>
