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

# Authentication

> How to authenticate with the e-invoice.be API

## Overview

The e-invoice.be API uses **Bearer Token Authentication** for all endpoints. You'll need to include your API key in the `Authorization` header of every request.

## Quick Start for New Users

If you're just getting started:

1. **Use the production API**: `https://api.e-invoice.be`
2. **Create a sandbox company**: In [app.e-invoice.be](https://app.e-invoice.be), click **Create sandbox company** to get a test-mode company and its own API key
3. **Start developing**: A sandbox company prevents real Peppol transmission while you build your integration

<Note>
  **For most users**, you only need to know about `api.e-invoice.be` and test mode.
</Note>

## Understanding the Setup

### What API Should I Use?

**Answer: Use `https://api.e-invoice.be`** - This single API works for both development and live transactions.

### How Do I Test Without Sending Real Invoices?

**Answer: Create a sandbox company.** A sandbox company runs in test mode: documents are emailed instead of being sent via Peppol. This lets you:

* Test your integration safely
* Verify invoice data and UBL generation
* See exactly what would be sent via Peppol

Create one from [app.e-invoice.be](https://app.e-invoice.be) — see [Test Mode](/environments) for the full walkthrough.

## API Host

### Production API: `api.e-invoice.be`

**Base URL:** `https://api.e-invoice.be`

This is the only API host you need:

* ✅ **For development**: With test mode enabled
* ✅ **For production**: With test mode disabled
* ✅ **Stable features**: Well-tested, production-ready
* ✅ **Standard rate limits**: Suitable for most applications

<Tip>
  Use `https://api.e-invoice.be` for everything. Test mode determines whether documents go out over Peppol, not the base URL.
</Tip>

## Test Mode Explained

Test mode is delivered through a **sandbox company** — a dedicated company that changes how documents are transmitted:

| Company                       | What Happens When You Send a Document            |
| ----------------------------- | ------------------------------------------------ |
| **Sandbox** (for development) | Email sent with UBL XML - no Peppol transmission |
| **Regular** (for production)  | Document sent via Peppol network to recipient    |

### Key Points About Test Mode

* It's determined by the company you authenticate as, not by which base URL you use
* A sandbox company has its **own API key**, separate from your live company's key
* A sandbox company cannot be converted to a live one — create a separate regular company to go live
* Everything else works the same (validation, webhooks, API endpoints, etc.)

<Note>
  Create a sandbox company from [app.e-invoice.be](https://app.e-invoice.be). See [Test Mode](/environments) for details.
</Note>

## Getting Your API Key

If you haven't already obtained your API key:

1. Log in to [app.e-invoice.be](https://app.e-invoice.be)
2. Go to **Settings** → **API Keys**
3. Click **Create API Key**
4. Copy and securely store your key

<Warning>
  Your API key is sensitive. Never share it publicly, commit it to version control, or expose it in client-side code.
</Warning>

## Making Authenticated Requests

Include your API key in the `Authorization` header with the `Bearer` prefix:

```bash theme={null}
curl -X GET "https://api.e-invoice.be/api/me/" \
     -H "Authorization: Bearer YOUR_API_KEY"
```

### Request Format

```
Authorization: Bearer YOUR_API_KEY
```

Replace `YOUR_API_KEY` with your actual API key.

<Tip>
  The same API key works whether or not test mode is enabled on your account.
</Tip>

## Code Examples

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

  // Most users should use the production API
  const BASE_URL = 'https://api.e-invoice.be';

  const api = axios.create({
    baseURL: BASE_URL,
    headers: {
      'Authorization': `Bearer ${process.env.E_INVOICE_API_KEY}`,
      'Content-Type': 'application/json'
    }
  });

  // Example: Get account info
  async function getAccountInfo() {
    try {
      const response = await api.get('/api/me/');
      console.log(response.data);
    } catch (error) {
      console.error('Error:', error.response?.data);
    }
  }
  ```

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

  API_KEY = os.environ.get('E_INVOICE_API_KEY')

  # Most users should use the production API
  BASE_URL = 'https://api.e-invoice.be'

  headers = {
      'Authorization': f'Bearer {API_KEY}',
      'Content-Type': 'application/json'
  }

  # Example: Get account info
  response = requests.get(f'{BASE_URL}/api/me/', headers=headers)
  print(response.json())
  ```

  ```php PHP theme={null}
  <?php
  $apiKey = getenv('E_INVOICE_API_KEY');

  // Most users should use the production API
  $baseUrl = 'https://api.e-invoice.be';

  $ch = curl_init();
  curl_setopt($ch, CURLOPT_URL, $baseUrl . '/api/me/');
  curl_setopt($ch, CURLOPT_HTTPHEADER, [
      'Authorization: Bearer ' . $apiKey,
      'Content-Type: application/json'
  ]);
  curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);

  $response = curl_exec($ch);
  curl_close($ch);

  $data = json_decode($response, true);
  print_r($data);
  ?>
  ```

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

  import (
      "fmt"
      "io"
      "net/http"
      "os"
  )

  func main() {
      apiKey := os.Getenv("E_INVOICE_API_KEY")

      // Most users should use the production API
      baseURL := "https://api.e-invoice.be"

      client := &http.Client{}
      req, _ := http.NewRequest("GET", baseURL+"/api/me/", nil)
      req.Header.Set("Authorization", "Bearer "+apiKey)
      req.Header.Set("Content-Type", "application/json")

      resp, err := client.Do(req)
      if err != nil {
          panic(err)
      }
      defer resp.Body.Close()

      body, _ := io.ReadAll(resp.Body)
      fmt.Println(string(body))
  }
  ```
</CodeGroup>

## Best Practices

### Store API Keys Securely

Use environment variables or secure credential management systems:

```bash theme={null}
# .env file (add to .gitignore!)
E_INVOICE_API_KEY=your_api_key_here
```

```javascript theme={null}
// Load from environment
require('dotenv').config();
const apiKey = process.env.E_INVOICE_API_KEY;
```

### Never Hardcode Keys

<Warning>
  ❌ **Don't do this:**

  ```javascript theme={null}
  const apiKey = 'sk_live_abc123...'; // Never hardcode!
  const baseUrl = 'https://api.e-invoice.be'; // Don't hardcode this either!
  ```

  ✅ **Do this instead:**

  ```javascript theme={null}
  const apiKey = process.env.E_INVOICE_API_KEY;
  const baseUrl = process.env.E_INVOICE_BASE_URL || 'https://api.e-invoice.be';
  ```
</Warning>

### Development Workflow

1. **Create a sandbox company** in [app.e-invoice.be](https://app.e-invoice.be) and use its API key
2. **Use the production API** (`api.e-invoice.be`) for development
3. **Switch to your live company's API key** when you're ready to go live

```bash theme={null}
# .env (same base URL; swap the API key per environment)
E_INVOICE_API_KEY=your_api_key
E_INVOICE_BASE_URL=https://api.e-invoice.be
```

<Note>
  You don't need to change your base URL or code when switching from development to production - just use your live company's API key and documents will be sent via Peppol instead of email. [Learn more about test mode →](/environments)
</Note>

### Rotate Keys Regularly

For security best practices:

1. Generate a new API key in your dashboard
2. Update your applications to use the new key
3. Delete the old key once migration is complete

### Use Multiple API Keys

Create separate API keys for:

* Sandbox companies (test mode) and real companies (production)
* Different applications or services
* Different team members or departments
* Programmatic access vs. manual testing

This allows you to rotate or revoke keys without affecting all systems.

## Error Responses

### 401 Unauthorized

If authentication fails, you'll receive a 401 error:

```json theme={null}
{
  "detail": "Invalid authentication"
}
```

**Common causes:**

* Missing `Authorization` header
* Invalid API key format
* Expired or revoked API key
* Typo in API key
* Using a sandbox company's API key for production sends (or vice versa)

### Troubleshooting

1. **Verify the header format**: Ensure you're using `Bearer YOUR_API_KEY`
2. **Check for whitespace**: Trim any extra spaces from your API key
3. **Confirm the workspace**: Make sure you're using the correct API key (sandbox company vs. real company)
4. **Test with curl**: Verify your key works with a simple curl command

```bash theme={null}
curl -X GET "https://api.e-invoice.be/api/me/" \
     -H "Authorization: Bearer YOUR_API_KEY" \
     -v
```

## Testing Your Authentication

Use the `/api/me/` endpoint to verify your authentication is working:

```bash theme={null}
curl -X GET "https://api.e-invoice.be/api/me/" \
     -H "Authorization: Bearer YOUR_API_KEY"
```

**Successful response:**

```json theme={null}
{
  "name": "Your Company",
  "company_name": "Your Company BV",
  "company_number": "0123456789",
  "company_country": "Belgium",
  "peppol_ids": ["0208:0123456789"],
  "plan": "starter",
  "credit_balance": 100
}
```

If you see this response, your authentication is working correctly!

## Next Steps

<CardGroup cols={2}>
  <Card title="Create Your First Invoice" icon="file-invoice" href="/guides/creating-invoices">
    Learn how to create and send e-invoices
  </Card>

  <Card title="Validate During Development" icon="check-circle" href="/guides/validation">
    Test your invoice data before sending
  </Card>
</CardGroup>
