| name | altinn |
| description | Integration with Altinn 3 APIs (instances, events, correspondence/meldinger, Maskinporten auth) using AT.Common.Altinn in this repository. Use this skill when consuming Altinn Storage, Altinn Events, Altinn Correspondence, or Maskinporten token exchange from a .NET backend. |
| license | MIT |
| metadata | {"domain":"backend","tags":"altinn altinn3 maskinporten storage events correspondence meldinger dotnet integration"} |
Altinn Skill โ Arbeidstilsynet/dotnet-common
Arbeidstilsynet.Common.Altinn (AT.Common.Altinn.Publish) provides typed HTTP clients and a higher-level adapter for interacting with Altinn 3 APIs, using Maskinporten for authentication.
Installation
dotnet add package Arbeidstilsynet.Common.Altinn
Dependency Injection Setup
Option A โ Full adapter (recommended)
Registers IAltinnAdapter, IAltinnMeldingerAdapter, and all low-level clients.
services.AddAltinnAdapter(builder.Environment, appSettings.MaskinportenConfiguration);
Option B โ Low-level clients only
Registers IAltinnStorageClient, IAltinnEventsClient, IAltinnCorrespondenceClient, IAltinnAuthenticationClient, IAltinnAppsClient, and IMaskinportenClient.
services.AddAltinnApiClients(builder.Environment, appSettings.MaskinportenConfiguration);
Both methods automatically resolve the correct Altinn base URLs based on environment:
| Environment | URLs used |
|---|
| Development | http://local.altinn.cloud:8000/ (platform) / http://local.altinn.cloud:8000/ (apps) |
| Non-production (other) | https://platform.tt02.altinn.no/ (platform) / https://dat.apps.tt02.altinn.no/ (apps) |
| Production | https://platform.altinn.no/ (platform) / https://dat.apps.altinn.no/ (apps) |
Override specific URLs by passing an AltinnConfiguration:
services.AddAltinnAdapter(
builder.Environment,
appSettings.MaskinportenConfiguration,
new AltinnConfiguration
{
StorageUrl = new Uri("https://custom-storage/"),
}
);
Configuration
MaskinportenConfiguration
{
"Maskinporten": {
"CertificatePrivateKey": "<base64-encoded RSA private key>",
"CertificateChain": "<base64-encoded cert chain>",
"KeyId": "<kid if pre-registered>",
"IntegrationId": "<integration id>",
"Scopes": ["altinn:instances.read", "altinn:instances.write"]
}
}
public record MaskinportenConfiguration
{
public required string PrivateKey { get; init; }
public string? CertificateChain { get; init; }
public string? KeyId { get; init; }
public required string IntegrationId { get; init; }
public required string[] Scopes { get; init; }
public Uri? MaskinportenUrl { get; init; }
}
AltinnConfiguration (optional overrides)
public record AltinnConfiguration
{
public string OrgId { get; init; } = "dat";
public required Uri AuthenticationUrl { get; init; }
public required Uri StorageUrl { get; init; }
public required Uri EventUrl { get; init; }
public required Uri CorrespondenceUrl { get; init; }
public required Uri AppBaseUrl { get; init; }
}
IAltinnAdapter โ High-level adapter
Inject via DI after calling AddAltinnAdapter.
public class MyService(IAltinnAdapter altinnAdapter)
{
public async Task ProcessEvent(AltinnCloudEvent cloudEvent)
{
var summary = await altinnAdapter.GetSummary(cloudEvent);
}
public async Task ManageSubscription(SubscriptionRequestDto request)
{
var subscription = await altinnAdapter.SubscribeForCompletedProcessEvents(request);
AltinnSubscription? existing = await altinnAdapter.GetAltinnSubscription(subscription.Id);
var success = await altinnAdapter.UnsubscribeForCompletedProcessEvents(subscription);
}
public async Task ScanInstances(string appId)
{
var instances = await altinnAdapter.GetNonCompletedInstances(appId);
var metadata = await altinnAdapter.GetMetadataForNonCompletedInstances(appId);
}
}
IAltinnMeldingerAdapter โ Correspondence adapter
Inject via DI after calling AddAltinnAdapter. Provides a high-level interface for Altinn correspondences (meldinger).
public class MyCorrespondenceService(IAltinnMeldingerAdapter meldingerAdapter)
{
public async Task SendCorrespondence(CorrespondenceRequest request, List<IFormFile>? attachments = null)
{
var response = await meldingerAdapter.CreateCorrespondence(request, attachments);
}
public async Task CheckCorrespondence(Guid correspondenceId)
{
AltinnCorrespondenceOverview? overview = await meldingerAdapter.GetCorrespondence(correspondenceId);
}
}
Low-level Clients
All clients are registered as Transient and use AddStandardResilienceHandler (built-in retry/circuit-breaker).
IAltinnStorageClient
var instance = await storageClient.GetInstance(new InstanceRequest { ... });
var instance = await storageClient.GetInstance(cloudEvent);
var stream = await storageClient.GetInstanceData(new InstanceDataRequest { ... });
var stream = await storageClient.GetInstanceData(absoluteUri);
var result = await storageClient.GetInstances(new InstanceQueryParameters { ... });
IAltinnEventsClient
var subscription = await eventsClient.Subscribe(new AltinnSubscriptionRequest { ... });
var response = await eventsClient.Unsubscribe(subscriptionId);
var subscription = await eventsClient.GetAltinnSubscription(subscriptionId);
IAltinnCorrespondenceClient
var response = await correspondenceClient.InitializeCorrespondence(request, attachments);
var overview = await correspondenceClient.GetCorrespondence(guid);
IAltinnAppsClient
var instance = await appsClient.CompleteInstance(appId, new InstanceRequest { ... });
IAltinnAuthenticationClient
Exchange Maskinporten tokens for Altinn tokens.
IMaskinportenClient
Get raw Maskinporten tokens.
Environment Behaviour
| Environment | Token provider |
|---|
IsDevelopment() | LocalAltinnTokenProvider (uses local cert/key directly) |
| All other | AltinnTokenProvider (Maskinporten โ Altinn token exchange) |
Extension Methods
AdapterExtensions, AltinnStorageClientExtensions, CorrespondenceRequestExtensions, and InstanceExtensions provide convenience helpers for common operations on Altinn model objects.
GetAllInstances (AltinnStorageClientExtensions)
Retrieves all Altinn instances matching the given query parameters, handling pagination internally.
var allInstances = await storageClient.GetAllInstances(new InstanceQueryParameters { ... });
Adding Altinn Integration โ Checklist
dotnet add package Arbeidstilsynet.Common.Altinn
- Add
MaskinportenConfiguration section to appsettings.json / secrets
- Bind config with
builder.Configuration.GetRequired<MyAppSettings>()
- Register with
services.AddAltinnAdapter(builder.Environment, maskinportenConfig)
- Inject
IAltinnAdapter (or specific low-level client) into your service
- In development, configure local certificate/key for
LocalAltinnTokenProvider