The Admin API is only available to resellers with an organization API key . This is a privileged API for managing multiple customer tenants. If you’re looking for standard invoice operations, see the regular API documentation .
Overview
The Admin API enables resellers to programmatically manage customer organizations (tenants), provision API credentials, and handle Peppol network registration on behalf of customers.
This is separate from the standard e-invoice.be API and uses different authentication.
Key Capabilities
Tenant Management - Create and manage customer organizations
API Key Provisioning - Generate and manage API keys for customers
Peppol Registration - Register customers on the Peppol network
Credential Rotation - Update and revoke API keys without customer involvement
Authentication
The Admin API requires an organization API key (also called admin API key), which is different from standard tenant API keys.
curl -X GET "https://api.e-invoice.be/api/admin/tenants" \
-H "Authorization: Bearer YOUR_ORGANIZATION_API_KEY"
Organization API keys are only provided to approved resellers. Contact [email protected] to discuss the reseller programme.
Tenant Management
List All Tenants
Retrieve all customer organizations under your reseller account:
curl -X GET "https://api.e-invoice.be/api/admin/tenants?skip=0&limit=100" \
-H "Authorization: Bearer YOUR_ORGANIZATION_API_KEY"
Query Parameters:
skip - Number of records to skip (default: 0)
limit - Maximum records to return (default: 100)
Response:
{
"tenants" : [
{
"id" : "tenant_abc123" ,
"name" : "customer-company-bvba" ,
"description" : "Customer Company BVBA" ,
"created_at" : "2024-10-24T10:00:00Z" ,
"updated_at" : "2024-10-24T10:00:00Z" ,
"is_deleted" : false
}
],
"total" : 1
}
Create a Tenant
Create a new customer organization:
curl -X POST "https://api.e-invoice.be/api/admin/tenants" \
-H "Authorization: Bearer YOUR_ORGANIZATION_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "customer-company-bvba",
"description": "Customer Company BVBA - Accounting Software Integration",
"company_number": "0123456789",
"company_tax_id": "BE0123456789",
"peppol_ids": ["0208:0123456789"]
}'
Request Body:
name (required) - Unique identifier for the tenant (lowercase, no spaces)
description (optional) - Human-readable description
company_number (optional) - Company registration number (e.g., CBE/KBO for Belgium, KvK for Netherlands, RCS for Luxembourg)
company_tax_id (optional) - Tax identification number (e.g., VAT number like BE0123456789)
peppol_ids (recommended) - Array containing the tenant’s Peppol ID
Response (201 Created):
{
"id" : "tenant_abc123" ,
"name" : "customer-company-bvba" ,
"description" : "Customer Company BVBA - Accounting Software Integration" ,
"company_number" : "0123456789" ,
"company_tax_id" : "BE0123456789" ,
"peppol_ids" : [ "0208:0123456789" ],
"created_at" : "2024-10-24T10:00:00Z" ,
"updated_at" : "2024-10-24T10:00:00Z" ,
"is_deleted" : false
}
You are responsible for determining and setting the correct Peppol ID for each tenant. Although peppol_ids is an array, the platform currently only supports a single Peppol ID per tenant. Setting the Peppol ID at tenant creation is important for proper Peppol registration later.
Company Number vs Tax ID
The tenant schema now separates company registration identifiers:
company_number - The official company registration number from the national business register:
Belgium: CBE/KBO number (e.g., 0123456789)
Netherlands: KvK number (Chamber of Commerce)
Luxembourg: RCS number (Registre de Commerce et des Sociétés)
Other countries: Equivalent business registration number
company_tax_id - The actual VAT or tax identification number:
Format includes country prefix (e.g., BE0123456789, NL123456789B01)
Used for tax purposes and invoicing
May be different from the company number in some jurisdictions
For Belgian companies, the CBE number (without “BE” prefix) is typically used in the Peppol ID as 0208:<CBE number>, while the full VAT number (with “BE” prefix) goes in company_tax_id.
The Peppol ID follows the format scheme:identifier:
Belgium (most common):
Format: 0208:<CBE number>
Example: 0208:0123456789
For Belgian companies, use scheme 0208 with the CBE/KBO number (enterprise number).
Example relationship:
company_number: 0123456789 (CBE number)
company_tax_id: BE0123456789 (VAT number)
peppol_ids: ["0208:0123456789"] (scheme 0208 + CBE number)
Other schemes:
9999 - DUNS number (international)
0088 - Global Location Number (GLN)
0184 - Dutch KVK number
9956 - Belgian company number (alternative)
Why Set Peppol ID During Creation?
The Peppol ID is used when:
Registering on the SMP (Service Metadata Publisher) - Maps the Peppol ID to e-invoice.be’s access point
Writing to the Peppol Directory - Creates a searchable entry for participant lookup
Routing documents - Ensures incoming invoices reach the correct tenant
Every tenant must have exactly one associated Peppol ID. Setting it during tenant creation ensures the tenant is properly configured before Peppol registration.
Use a consistent naming convention for tenant names, such as customer-slug or company-id. This makes it easier to manage multiple customers.
Get a Tenant
Retrieve details for a specific tenant:
curl -X GET "https://api.e-invoice.be/api/admin/tenants/tenant_abc123" \
-H "Authorization: Bearer YOUR_ORGANIZATION_API_KEY"
Update a Tenant
Update tenant information:
curl -X PUT "https://api.e-invoice.be/api/admin/tenants/tenant_abc123" \
-H "Authorization: Bearer YOUR_ORGANIZATION_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "customer-company-bvba",
"description": "Updated description",
"company_number": "0123456789",
"company_tax_id": "BE0123456789",
"peppol_ids": ["0208:0123456789"]
}'
You can update the company_number, company_tax_id, and peppol_ids fields after tenant creation if needed.
Delete a Tenant
Soft-delete a tenant (marks as deleted, doesn’t remove data):
curl -X DELETE "https://api.e-invoice.be/api/admin/tenants/tenant_abc123" \
-H "Authorization: Bearer YOUR_ORGANIZATION_API_KEY"
API Key Management
Provision and manage API keys for customer tenants.
Create an API Key
Generate a new API key for a tenant:
curl -X POST "https://api.e-invoice.be/api/admin/tenants/tenant_abc123/api-keys" \
-H "Authorization: Bearer YOUR_ORGANIZATION_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "production-key",
"description": "Production API key for Customer Company"
}'
Request Body:
name (required) - Identifier for the API key
description (optional) - Purpose or environment
Response:
{
"id" : "key_xyz789" ,
"tenant_id" : "tenant_abc123" ,
"name" : "production-key" ,
"description" : "Production API key for Customer Company" ,
"key" : "einv_prod_abc123def456..." ,
"created_at" : "2024-10-24T10:00:00Z" ,
"updated_at" : "2024-10-24T10:00:00Z" ,
"is_deleted" : false
}
The key field is only returned when creating a new API key. Store it securely and provide it to your customer. It cannot be retrieved again later.
List API Keys
Get all API keys for a tenant:
curl -X GET "https://api.e-invoice.be/api/admin/tenants/tenant_abc123/api-keys?limit=100" \
-H "Authorization: Bearer YOUR_ORGANIZATION_API_KEY"
Response:
{
"api_keys" : [
{
"id" : "key_xyz789" ,
"tenant_id" : "tenant_abc123" ,
"name" : "production-key" ,
"description" : "Production API key" ,
"created_at" : "2024-10-24T10:00:00Z" ,
"updated_at" : "2024-10-24T10:00:00Z" ,
"is_deleted" : false
}
],
"total" : 1
}
The actual API key value is not returned when listing keys (only on creation).
Get Latest API Key
Retrieve the most recently created API key for a tenant:
curl -X GET "https://api.e-invoice.be/api/admin/tenants/tenant_abc123/api-keys/latest" \
-H "Authorization: Bearer YOUR_ORGANIZATION_API_KEY"
Update an API Key
Update API key metadata (name/description):
curl -X PUT "https://api.e-invoice.be/api/admin/tenants/tenant_abc123/api-keys/key_xyz789" \
-H "Authorization: Bearer YOUR_ORGANIZATION_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "production-key-v2",
"description": "Updated production key"
}'
Revoke an API Key
Delete (revoke) an API key:
curl -X DELETE "https://api.e-invoice.be/api/admin/tenants/tenant_abc123/api-keys/key_xyz789" \
-H "Authorization: Bearer YOUR_ORGANIZATION_API_KEY"
For credential rotation, create a new API key, update your customer’s configuration, then revoke the old key.
Peppol Registration
Manage Peppol network registration for customer tenants.
Check Registration Status
Check if a tenant is registered on Peppol:
curl -X GET "https://api.e-invoice.be/api/admin/tenants/tenant_abc123/peppol/status" \
-H "Authorization: Bearer YOUR_ORGANIZATION_API_KEY"
Response:
{
"registered" : true ,
"peppol_id" : "0208:0123456789" ,
"status" : "active" ,
"registered_at" : "2024-10-24T10:00:00Z"
}
Register on Peppol
Register a tenant on the Peppol network:
curl -X POST "https://api.e-invoice.be/api/admin/tenants/tenant_abc123/peppol/register" \
-H "Authorization: Bearer YOUR_ORGANIZATION_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"peppol_id": "0208:0123456789",
"company_name": "Customer Company BVBA"
}'
For Belgian companies , the system can automatically fetch company data from KBO (Crossroads Bank for Enterprises):
curl -X POST "https://api.e-invoice.be/api/admin/tenants/tenant_abc123/peppol/register" \
-H "Authorization: Bearer YOUR_ORGANIZATION_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"peppol_id": "0208:0123456789"
}'
The system will:
Fetch company details from KBO using the CBE number
Register with the SMP (Service Metadata Publisher)
Create a business card on the Peppol network
Peppol registration is not available for tenants in test mode. Ensure the tenant is in production mode before attempting registration.
Update Business Card
Update the business card information on Peppol:
curl -X POST "https://api.e-invoice.be/api/admin/tenants/tenant_abc123/peppol/business-card" \
-H "Authorization: Bearer YOUR_ORGANIZATION_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"company_name": "Updated Company Name BVBA"
}'
Currently, only company name updates are supported for business cards.
Unregister from Peppol
Remove a tenant from the Peppol network:
curl -X POST "https://api.e-invoice.be/api/admin/tenants/tenant_abc123/peppol/unregister" \
-H "Authorization: Bearer YOUR_ORGANIZATION_API_KEY"
This will:
Remove SMP registration
Delete the business card
Mark the tenant as unregistered
Complete Workflow Example
Here’s a complete Node.js example showing the typical reseller workflow:
const axios = require ( 'axios' );
const adminApi = axios . create ({
baseURL: 'https://api.e-invoice.be' ,
headers: {
'Authorization' : `Bearer ${ process . env . ORGANIZATION_API_KEY } ` ,
'Content-Type' : 'application/json'
}
});
async function onboardNewCustomer ( customerData ) {
try {
// 1. Create tenant with company details and Peppol ID
console . log ( 'Creating tenant...' );
const tenant = await adminApi . post ( '/api/admin/tenants' , {
name: customerData . slug ,
description: customerData . companyName ,
company_number: customerData . companyNumber ,
company_tax_id: customerData . vatNumber ,
peppol_ids: [ customerData . peppolId ]
});
console . log ( '✓ Tenant created:' , tenant . data . id );
console . log ( '✓ Company number:' , customerData . companyNumber );
console . log ( '✓ Tax ID:' , customerData . vatNumber );
console . log ( '✓ Peppol ID set:' , customerData . peppolId );
// 2. Create API key for customer
console . log ( 'Generating API key...' );
const apiKey = await adminApi . post (
`/api/admin/tenants/ ${ tenant . data . id } /api-keys` ,
{
name: 'production-key' ,
description: 'Production API key'
}
);
console . log ( '✓ API key created:' , apiKey . data . id );
// IMPORTANT: Store this key securely and provide to customer
const customerApiKey = apiKey . data . key ;
console . log ( 'Customer API key:' , customerApiKey );
// 3. Register on Peppol (for Belgian companies)
console . log ( 'Registering on Peppol...' );
const registration = await adminApi . post (
`/api/admin/tenants/ ${ tenant . data . id } /peppol/register` ,
{
peppol_id: customerData . peppolId
}
);
console . log ( '✓ Peppol registration complete' );
// 4. Return customer credentials
return {
tenantId: tenant . data . id ,
apiKey: customerApiKey ,
peppolId: customerData . peppolId ,
status: 'active'
};
} catch ( error ) {
console . error ( 'Onboarding failed:' , error . response ?. data || error . message );
throw error ;
}
}
// Usage
const customerData = {
slug: 'customer-company-bvba' ,
companyName: 'Customer Company BVBA' ,
companyNumber: '0123456789' , // CBE/KBO number
vatNumber: 'BE0123456789' , // Full VAT number
peppolId: '0208:0123456789' // Peppol ID (scheme 0208 + CBE number)
};
onboardNewCustomer ( customerData )
. then ( credentials => {
console . log ( 'Customer onboarded successfully:' );
console . log ( '- Tenant ID:' , credentials . tenantId );
console . log ( '- API Key:' , credentials . apiKey );
console . log ( '- Peppol ID:' , credentials . peppolId );
});
Key Rotation Example
Rotate API keys without customer downtime:
async function rotateApiKey ( tenantId , oldKeyId ) {
try {
// 1. Create new API key
console . log ( 'Creating new API key...' );
const newKey = await adminApi . post (
`/api/admin/tenants/ ${ tenantId } /api-keys` ,
{
name: 'production-key-v2' ,
description: 'Rotated production key'
}
);
console . log ( '✓ New key created:' , newKey . data . id );
// 2. Provide new key to customer
// (Send via secure channel, update their configuration)
const newApiKey = newKey . data . key ;
console . log ( 'New API key:' , newApiKey );
// 3. Wait for customer to switch over
console . log ( 'Waiting for customer to update configuration...' );
await new Promise ( resolve => setTimeout ( resolve , 3600000 )); // 1 hour
// 4. Revoke old key
console . log ( 'Revoking old API key...' );
await adminApi . delete (
`/api/admin/tenants/ ${ tenantId } /api-keys/ ${ oldKeyId } `
);
console . log ( '✓ Old key revoked' );
return newKey . data ;
} catch ( error ) {
console . error ( 'Key rotation failed:' , error . response ?. data || error . message );
throw error ;
}
}
Error Handling
Common error responses:
401 Unauthorized
{
"detail" : "Invalid authentication credentials"
}
Solution : Verify your organization API key is correct and active.
404 Not Found
{
"detail" : "Tenant not found"
}
Solution : Check the tenant ID is correct and the tenant exists.
409 Conflict
{
"detail" : "A tenant with similar name already exists"
}
Solution : Choose a different tenant name.
422 Validation Error
{
"detail" : [
{
"loc" : [ "body" , "name" ],
"msg" : "field required" ,
"type" : "value_error.missing"
}
]
}
Solution : Ensure all required fields are provided.
Best Practices
Never log or display organization API keys
Store customer API keys securely (encrypted database)
Provide keys to customers via secure channels only
Implement key rotation policies (e.g., every 90 days)
// ✓ Good: Secure handling
const encryptedKey = encrypt ( apiKey . data . key );
await database . storeCustomerKey ( customerId , encryptedKey );
// ✗ Bad: Insecure handling
console . log ( 'API Key:' , apiKey . data . key );
localStorage . setItem ( 'key' , apiKey . data . key );
Use consistent, predictable tenant names: // ✓ Good patterns
const tenantName = 'customer-company-bvba' ;
const tenantName = `cust- ${ customerId } ` ;
const tenantName = companyName . toLowerCase (). replace ( / \s + / g , '-' );
// ✗ Bad patterns
const tenantName = 'Customer 1' ;
const tenantName = Math . random (). toString ();
Implement idempotent operations and error recovery: async function createTenantSafely ( name , description ) {
try {
return await adminApi . post ( '/api/admin/tenants' , { name , description });
} catch ( error ) {
if ( error . response ?. status === 409 ) {
// Tenant already exists, fetch it instead
console . log ( 'Tenant exists, fetching...' );
const tenants = await adminApi . get ( '/api/admin/tenants' );
return tenants . data . tenants . find ( t => t . name === name );
}
throw error ;
}
}
Log all admin operations for compliance: async function auditedTenantCreate ( tenantData ) {
const result = await adminApi . post ( '/api/admin/tenants' , tenantData );
await auditLog . create ({
action: 'TENANT_CREATE' ,
tenant_id: result . data . id ,
admin_user: currentUser . id ,
timestamp: new Date (),
details: { name: tenantData . name }
});
return result . data ;
}
Peppol Registration Checks
Always verify registration prerequisites: async function registerOnPeppol ( tenantId , peppolId ) {
// 1. Check tenant is not in test mode
const tenant = await adminApi . get ( `/api/admin/tenants/ ${ tenantId } ` );
if ( tenant . data . test_mode ) {
throw new Error ( 'Cannot register test-mode tenant on Peppol' );
}
// 2. Verify Peppol ID format
if ( ! / ^ \d {4} : \d + $ / . test ( peppolId )) {
throw new Error ( 'Invalid Peppol ID format' );
}
// 3. Register
return await adminApi . post (
`/api/admin/tenants/ ${ tenantId } /peppol/register` ,
{ peppol_id: peppolId }
);
}
Environment Differences
The Admin API is available on both environments:
Environment Base URL Production https://api.e-invoice.beDevelopment https://api-dev.e-invoice.be
Use the development environment for testing your integration before going live.
Rate Limiting
Admin API requests are subject to rate limiting:
100 requests per minute per organization API key
1000 requests per hour per organization API key
Exceeding limits returns 429 Too Many Requests.
Support
For Admin API access or technical questions: