Organizations & Multi-Tenancy
GoRoute is built for platforms that serve multiple businesses. Each business operates within its own organization, with complete data isolation.
What is an Organization?
An organization represents a single business entity in GoRoute. Each organization has:
- A unique identifier (
org_id) - Its own Peppol participant registration(s)
- Isolated invoice and transaction data
- Separate webhook configurations
- Independent rate limits
Multi-Tenant Architecture
┌─────────────────────────────────────────────────────┐
│ Your Platform │
├─────────────────────────────────────────────────────┤
│ Customer A │ Customer B │ Customer C │
│ (org_001) │ (org_002) │ (org_003) │
└──────┬───────┴──────┬───────┴──────┬────────────────┘
│ │ │
▼ ▼ ▼
┌─────────────────────────────────────────────────────┐
│ GoRoute API │
│ Complete data isolation per org_id │
└─────────────────────────────────────────────────────┘
│ │ │
▼ ▼ ▼
┌─────────────────────────────────────────────────────┐
│ Peppol Network │
└─────────────────────────────────────────────────────┘
Creating an Organization
curl -X POST https://app.goroute.ai/peppol-api/api/v1/organizations \
-H "X-API-Key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "Acme Corporation",
"legal_name": "Acme Corporation B.V.",
"country": "NL",
"vat_number": "NL123456789B01",
"address": {
"street": "123 Business Street",
"city": "Amsterdam",
"postal_code": "1012 AB",
"country": "NL"
},
"contact": {
"email": "invoices@acme.example.com",
"phone": "+31201234567"
}
}'
Response:
{
"org_id": "org_abc123def456",
"name": "Acme Corporation",
"legal_name": "Acme Corporation B.V.",
"country": "NL",
"status": "active",
"created_at": "2026-01-26T10:00:00Z"
}
Organization Scoping
All API operations are scoped to an organization. There are two approaches:
Approach 1: Implicit (Recommended)
Your API key is associated with a default organization:
# Uses the default org for your API key
curl -X GET https://app.goroute.ai/peppol-api/api/v1/invoices \
-H "X-API-Key: YOUR_API_KEY"
Approach 2: Explicit
Specify the organization in the request:
# Explicitly specify org_id
curl -X GET https://app.goroute.ai/peppol-api/api/v1/organizations/org_abc123/invoices \
-H "X-API-Key: YOUR_API_KEY"
Or use the header:
curl -X GET https://app.goroute.ai/peppol-api/api/v1/invoices \
-H "X-API-Key: YOUR_API_KEY" \
-H "X-Organization-Id: org_abc123"
Data Isolation
Each organization's data is completely isolated:
| Data Type | Isolation |
|---|---|
| Invoices | ✅ Fully isolated |
| Transactions | ✅ Fully isolated |
| Participants | ✅ Fully isolated |
| Webhooks | ✅ Fully isolated |
| API Keys | ✅ Scoped per org |
| Rate Limits | ✅ Independent per org |
Security Guarantee
There is no way to access another organization's data through the API. All queries automatically filter by org_id.
Organization Status
| Status | Description |
|---|---|
pending | Created, awaiting verification |
active | Fully operational |
suspended | Temporarily disabled (e.g., billing issue) |
closed | Permanently closed |
Managing Organizations
List Organizations
curl -X GET https://app.goroute.ai/peppol-api/api/v1/organizations \
-H "X-API-Key: YOUR_API_KEY"
Get Organization Details
curl -X GET https://app.goroute.ai/peppol-api/api/v1/organizations/org_abc123 \
-H "X-API-Key: YOUR_API_KEY"
Update Organization
curl -X PATCH https://app.goroute.ai/peppol-api/api/v1/organizations/org_abc123 \
-H "X-API-Key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"contact": {
"email": "newemail@acme.example.com"
}
}'
Platform Integration Pattern
For platforms serving multiple customers:
class GoRouteClient:
def __init__(self, api_key: str):
self.api_key = api_key
self.base_url = "https://app.goroute.ai/peppol-api"
def send_invoice(self, org_id: str, invoice_data: dict):
"""Send invoice for a specific organization."""
response = requests.post(
f"{self.base_url}/api/v1/invoices",
headers={
"X-API-Key": self.api_key,
"X-Organization-Id": org_id # Scope to specific org
},
json=invoice_data
)
return response.json()
def get_transactions(self, org_id: str):
"""Get transactions for a specific organization."""
response = requests.get(
f"{self.base_url}/api/v1/transactions",
headers={
"X-API-Key": self.api_key,
"X-Organization-Id": org_id
}
)
return response.json()
Webhooks per Organization
Each organization can have its own webhook configuration:
curl -X POST https://app.goroute.ai/peppol-api/api/v1/organizations/org_abc123/webhooks \
-H "X-API-Key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"url": "https://yourplatform.com/webhooks/org_abc123",
"events": ["invoice.delivered", "invoice.received"],
"secret": "whsec_..."
}'
Best Practices
- One org per business — Create a separate organization for each customer
- Store org_id — Map your internal customer ID to GoRoute org_id
- Validate ownership — Ensure users can only access their own organization
- Separate webhooks — Configure unique webhook endpoints per organization