Skip to main content

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:

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

StatusDescription
pendingCreated, awaiting verification
activeFully operational
suspendedTemporarily disabled (e.g., billing issue)
closedPermanently 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

  1. One org per business — Create a separate organization for each customer
  2. Store org_id — Map your internal customer ID to GoRoute org_id
  3. Validate ownership — Ensure users can only access their own organization
  4. Separate webhooks — Configure unique webhook endpoints per organization

Next Steps