← Back to tracks
Technology Partner Integration
Exchange documents as part of your SaaS product. Register as a technology partner, subscribe to events, and integrate document exchange into your platform.
1
Register as technology partner
Create a partner account with OAuth application and elevated API access.
using Semansys.CompliancePlatform.Client;
var client = new CompliancePlatformClient("https://api.semansys.com", apiKey);
var partner = await client.Partners.RegisterAsync(new RegisterPartnerRequest
{
CompanyName = "CloudBilling B.V.",
ContactEmail = "partnerships@cloudbilling.nl",
Tier = "technology",
OAuthApp = new OAuthAppConfig
{
AppName = "CloudBilling Platform",
RedirectUris = new[] { "https://cloudbilling.nl/auth/callback" },
GrantTypes = new[] { "client_credentials" },
Scopes = new[] { "documents:write", "documents:read", "webhooks:manage", "discovery:read" }
}
});
Console.WriteLine($"Partner ID: {partner.PartnerId}");
Console.WriteLine($"OAuth Client ID: {partner.OAuthApp.ClientId}");2
Subscribe to relevant event types via webhooks
Register webhooks for real-time document lifecycle notifications.
var webhook = await client.Webhooks.RegisterAsync(new RegisterWebhookRequest
{
Url = "https://cloudbilling.nl/api/webhooks/semansys",
EventTypes = new[] { "document.created.v1", "document.validated.v1", "document.rendered.v1", "document.sent.v1", "document.delivery.failed.v1", "route.completed.v1", "route.failed.v1" },
Filter = new WebhookFilter { LegalEntityIds = new[] { entityId } }
});
Console.WriteLine($"Webhook ID: {webhook.WebhookId}");
Console.WriteLine($"Signing Secret: {webhook.SigningSecret}");3
Implement document receipt and acknowledgement
Build a webhook handler that verifies signatures and processes documents.
app.MapPost("/api/webhooks/semansys", async (HttpContext ctx) =>
{
var signature = ctx.Request.Headers["X-Semansys-Signature"].ToString();
var body = await new StreamReader(ctx.Request.Body).ReadToEndAsync();
if (!WebhookVerifier.Verify(signature, body, signingSecret))
return Results.Unauthorized();
var evt = JsonSerializer.Deserialize<WebhookEvent>(body);
if (evt.EventType == "document.created.v1")
{
var payload = await client.Documents.DownloadPayloadAsync(evt.DocumentId);
await ProcessInboundDocument(evt.DocumentId, payload);
}
return Results.Ok();
});4
Integrate discovery lookup before sending
Check if the receiver is registered on the Peppol network before sending.
var discovery = await client.Discovery.LookupAsync(new DiscoveryLookupRequest
{
Identifier = "0106:87654321",
DocumentType = "urn:oasis:names:specification:ubl:schema:xsd:Invoice-2::Invoice"
});
if (discovery.Found)
{
Console.WriteLine($"Receiver supports Peppol: {discovery.EndpointUrl}");
var result = await client.Documents.CreateAsync(new CreateDocumentRequest
{
SenderLegalEntityId = myEntityId,
Receiver = new ReceiverRef { Identifier = "0106:87654321" },
Content = new PayloadContent { Kind = "payload", Format = "ubl", Data = File.ReadAllBytes("invoice.xml") }
});
}
else
{
Console.WriteLine("Receiver not found — consider email delivery");
}