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


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.docs-dispatcher.io/docs-dispatcher/authentication/basic-auth.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
