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");
}