Skip to main content

Partner Verification

Verify that your trading partners are legitimate and can receive Peppol documents.

Why Verify Partners?

Before sending invoices to a new trading partner, verify:

  1. Identity — Is this the right company?
  2. Registration — Are they on the Peppol network?
  3. Capabilities — Can they receive your document type?
  4. Access Point — Is their AP active and trusted?

Quick Verification

import requests

def verify_partner(scheme: str, identifier: str) -> dict:
"""Verify a trading partner."""
response = requests.get(
"https://app.goroute.ai/peppol-api/api/v1/partners/verify",
params={
"scheme": scheme,
"identifier": identifier
},
headers={"X-API-Key": "your_api_key"}
)
return response.json()


# Verify a partner
result = verify_partner("0106", "12345678")

if result["verified"]:
print(f"✅ Partner verified: {result['name']}")
print(f" Can receive: {', '.join(result['document_types'])}")
else:
print(f"❌ Verification failed: {result['reason']}")

Verification Response

{
"verified": true,
"partner": {
"scheme": "0106",
"identifier": "12345678",
"name": "Partner Company BV",
"country": "NL",
"verified_at": "2024-01-15T10:30:00Z"
},
"peppol_status": {
"registered": true,
"registration_date": "2023-06-15",
"access_point": {
"name": "Storecove",
"peppol_id": "POP000123",
"status": "active"
}
},
"capabilities": {
"can_receive_invoice": true,
"can_receive_credit_note": true,
"can_receive_order": false,
"supported_document_types": [
"Invoice",
"CreditNote"
]
},
"trust_indicators": {
"verified_identity": true,
"active_on_peppol": true,
"recent_activity": true,
"trust_score": 95
},
"checks_performed": [
{"check": "smp_lookup", "passed": true},
{"check": "identifier_validation", "passed": true},
{"check": "ap_status", "passed": true}
]
}

Verification Checks

CheckDescription
SMP LookupPartner is registered in Peppol SMP
Identifier ValidationPeppol ID format is valid
AP StatusAccess Point is active and reachable
Certificate ValidityAP certificate is valid
Recent ActivityPartner has recent transactions

Verification Levels

Level 1: Basic Lookup

Check if participant exists on Peppol:

result = verify_partner(
scheme="0106",
identifier="12345678"
)

# Returns: registered true/false

Level 2: Full Verification

Deep verification including business registry checks:

result = requests.get(
"https://app.goroute.ai/peppol-api/api/v1/partners/verify",
params={
"scheme": "0106",
"identifier": "12345678",
"level": "full"
},
headers={"X-API-Key": "your_api_key"}
)

# Includes: Business registry validation, trade register check

Level 3: Extended Due Diligence

For high-value or sensitive transactions:

result = requests.get(
"https://app.goroute.ai/peppol-api/api/v1/partners/verify",
params={
"scheme": "0106",
"identifier": "12345678",
"level": "extended"
},
headers={"X-API-Key": "your_api_key"}
)

# Includes: Credit check, sanctions screening

Batch Verification

Verify multiple partners at once:

def batch_verify(partners: list[dict]) -> dict:
"""Verify multiple partners in one request."""
response = requests.post(
"https://app.goroute.ai/peppol-api/api/v1/partners/verify/batch",
headers={
"X-API-Key": "your_api_key",
"Content-Type": "application/json"
},
json={"partners": partners}
)
return response.json()


# Verify your customer list
results = batch_verify([
{"scheme": "0106", "identifier": "12345678"},
{"scheme": "0106", "identifier": "87654321"},
{"scheme": "0208", "identifier": "0123456789"}
])

for result in results["results"]:
status = "✅" if result["verified"] else "❌"
print(f"{status} {result['scheme']}:{result['identifier']}: {result['reason']}")

Integration Patterns

Pre-Send Verification

Verify before every send:

class SecureSender:
def send_invoice(self, invoice_xml: str) -> dict:
# Extract receiver
receiver = self.extract_receiver(invoice_xml)

# Verify partner
verification = verify_partner(receiver["scheme"], receiver["identifier"])

if not verification["verified"]:
raise ValueError(f"Partner not verified: {verification['reason']}")

if not verification["capabilities"]["can_receive_invoice"]:
raise ValueError("Partner cannot receive invoices")

# Proceed with sending
return self.do_send(invoice_xml)

Onboarding Verification

Verify new trading partners during onboarding:

async def onboard_partner(partner_data: dict) -> dict:
"""Onboard a new trading partner with verification."""

# Verify on Peppol
verification = verify_partner(
partner_data["peppol_scheme"],
partner_data["peppol_id"]
)

if not verification["verified"]:
return {
"status": "manual_review",
"reason": verification["reason"],
"message": "Partner requires manual verification"
}

# Create partner record
partner = await create_partner(
**partner_data,
verified=True,
verification_date=datetime.utcnow()
)

return {"status": "active", "partner_id": partner.id}

Periodic Re-verification

Re-verify partners periodically:

from datetime import datetime, timedelta

async def reverify_partners():
"""Re-verify partners who haven't been verified recently."""

stale_threshold = datetime.utcnow() - timedelta(days=30)

partners = await db.query(
"SELECT * FROM partners WHERE last_verified < $1",
stale_threshold
)

for partner in partners:
verification = verify_partner(partner.scheme, partner.identifier)

await db.execute(
"""UPDATE partners
SET verified = $1,
last_verified = $2,
verification_data = $3
WHERE id = $4""",
verification["verified"],
datetime.utcnow(),
json.dumps(verification),
partner.id
)

if not verification["verified"]:
await notify_admin(f"Partner {partner.name} failed re-verification")

Verification Webhook

Get notified of partner status changes:

# Register for partner status webhooks
response = requests.post(
"https://app.goroute.ai/peppol-api/api/v1/webhooks",
headers={"X-API-Key": "your_api_key"},
json={
"url": "https://your-app.com/webhooks/peppol",
"events": ["partner.status_changed"]
}
)

# Webhook payload
{
"type": "partner.status_changed",
"data": {
"scheme": "0106",
"identifier": "12345678",
"previous_status": "active",
"new_status": "deregistered",
"reason": "Participant removed from SMP",
"detected_at": "2024-01-15T10:30:00Z"
}
}

Trust Score

GoRoute calculates a trust score based on:

FactorWeightDescription
Peppol Registration30%Active SMP registration
Registration Age15%Longer = more trusted
Transaction History25%Successful document exchanges
AP Reputation15%Access Point reliability
Identifier Validity15%Valid business registry number
# Get detailed trust score
result = verify_partner("0106", "12345678")

trust = result["trust_indicators"]
print(f"Trust Score: {trust['trust_score']}/100")

if trust["trust_score"] >= 80:
print("High trust - automatic processing")
elif trust["trust_score"] >= 50:
print("Medium trust - standard review")
else:
print("Low trust - manual verification required")

Next Steps