Back to tracks

System Integrator Integration

Build bespoke compliance solutions for your clients. Set up OAuth apps, onboard legal entities, configure processing routes, and monitor everything via webhooks.

1

Register an OAuth 2.0 app

Create an OAuth application for server-to-server or user-facing integrations.

using Semansys.CompliancePlatform.Client;

var client = new CompliancePlatformClient("https://api.semansys.com", apiKey);

var app = await client.OAuth.RegisterAppAsync(new RegisterOAuthAppRequest
{
    AppName = "Acme Integration Hub",
    RedirectUris = new[] { "https://integration.acme.com/callback" },
    GrantTypes = new[] { "authorization_code", "client_credentials" },
    Scopes = new[] { "documents:write", "entities:manage", "routes:manage" }
});

Console.WriteLine($"Client ID: {app.ClientId}");
Console.WriteLine($"Client Secret: {app.ClientSecret}");
2

Onboard a legal entity

Register your client with their business identifiers and jurisdiction defaults.

var entity = await client.LegalEntities.CreateAsync(new CreateLegalEntityRequest
{
    Name = "Client Corp B.V.",
    Jurisdiction = "NL",
    Identifiers = new[]
    {
        new IdentifierRequest { Type = "kvk", Value = "12345678" },
        new IdentifierRequest { Type = "vat", Value = "NL123456789B01" },
        new IdentifierRequest { Type = "peppol", Value = "0106:12345678" }
    },
    Defaults = new EntityDefaults
    {
        PreferredDeliveryChannel = "peppol",
        PreferredValidationProfile = "si-ubl-2.0"
    }
});

Console.WriteLine($"Legal Entity ID: {entity.LegalEntityId}");
3

Configure a processing route

Define how documents are validated, converted, and delivered.

var route = await client.Routes.CreateAsync(new CreateRouteRequest
{
    LegalEntityId = entity.LegalEntityId,
    Name = "Standard NL Invoice Route",
    Trigger = "ApiSubmit",
    Stages = new[]
    {
        new StageRequest { Steps = new[] { new StepRequest { Type = "Validate", Config = new { Profile = "si-ubl-2.0" } } } },
        new StageRequest { Steps = new[] { new StepRequest { Type = "Convert", Config = new { TargetFormat = "ubl" } }, new StepRequest { Type = "Convert", Config = new { TargetFormat = "pdf" } } } },
        new StageRequest { Steps = new[] { new StepRequest { Type = "Deliver", Config = new { Channel = "peppol" } } } }
    }
});

Console.WriteLine($"Route ID: {route.RouteId}");
4

Submit a document through the configured route

Send a document on behalf of your client through the configured pipeline.

var result = await client.Documents.CreateAsync(new CreateDocumentRequest
{
    SenderLegalEntityId = entity.LegalEntityId,
    Receiver = new ReceiverRef { Identifier = "0106:87654321" },
    Content = new SsmContent { Kind = "ssm", Ssm = new SsmInvoice { InvoiceNumber = "SI-2026-001", IssueDate = "2026-03-16", CurrencyCode = "EUR" } }
});

Console.WriteLine($"Document ID: {result.DocumentId}");
5

Monitor via webhooks

Subscribe to lifecycle events and verify webhook signatures.

var webhook = await client.Webhooks.RegisterAsync(new RegisterWebhookRequest
{
    Url = "https://integration.acme.com/webhooks/semansys",
    EventTypes = new[] { "document.created.v1", "document.validated.v1", "document.sent.v1", "document.delivery.failed.v1", "route.completed.v1", "route.failed.v1" }
});

app.MapPost("/einvoicing/webhooks/semansys", async (HttpContext ctx) =>
{
    var isValid = WebhookVerifier.Verify(
        ctx.Request.Headers["X-Semansys-Signature"],
        await new StreamReader(ctx.Request.Body).ReadToEndAsync(),
        webhook.SigningSecret);
    if (!isValid) return Results.Unauthorized();
    return Results.Ok();
});