Offentlig sektor i Sverige digitaliseras i en rasande takt, och i navet av denna utveckling hittar vi Myndigheten för digital förvaltning (DIGG). Med lanseringen av REST API-profil version 2.0.0 (nu den 16 juni 2026) har ribban höjts. Fokus har flyttats från isolerade system till hur API:er samverkar i stora, distribuerade kedjor över organisationsgränser.

För oss som bygger system i .NET-ekosystemet är tajmingen perfekt. Med .NET 10 har vi inbyggda, kraftfulla verktyg för att möta dessa nya, strikta krav. Här går vi igenom de största nyheterna i v2.0.0 (och uppstramningarna från 1.2.0) och tittar på hur du implementerar dem rent praktiskt i C#.


1. Den stora nyheten: Spårbarhet över systemgränser

När system kopplas samman i långa kedjor (Klient -> Portal -> Gateway -> Tjänst -> Register) blir felsökning en mardröm om man saknar en röd tråd. Version 2.0.0 introducerar ett helt nytt kapitel med skarpa krav på spårbarhet och korrelation.

DIGG förordar starkt industristandarden W3C Trace Context (traceparent-headern), med traditionella X-Correlation-ID som godkänd fallback. Detta måste propagera genom hela din anropskedja.

Implementering i .NET 10 med OpenTelemetry

I .NET 10 är distribuerad spårning förstklassiga medborgare. Vi behöver inte bygga egna komplexa ramverk, utan vi kopplar in OpenTelemetry och skapar en anpassad middleware för att säkerställa att vi även stödjer X-Correlation-ID för äldre konsumenter.

I Program.cs:

using OpenTelemetry.Trace;
using OpenTelemetry.Resources;

var builder = WebApplication.CreateBuilder(args);

// Aktivera W3C-spårning och skicka vidare i utgående HTTP-anrop automatiskt
builder.Services.AddOpenTelemetry()
    .WithTracing(tracing => tracing
        .SetResourceBuilder(ResourceBuilder.CreateDefault().AddService("MyndighetsAPI-Kunder"))
        .AddAspNetCoreInstrumentation()
        .AddHttpClientInstrumentation());

builder.Services.AddControllers();
var app = builder.Build();

// Registrera vår Digg-middleware (se nedan)
app.UseMiddleware<DiggTraceabilityMiddleware>();
app.MapControllers();
app.Run();

En anpassad Middleware (DiggTraceabilityMiddleware.cs): Denna ser till att ID:t loggas strukturerat och alltid returneras till klienten.

public class DiggTraceabilityMiddleware
{
    private readonly RequestDelegate _next;

    public DiggTraceabilityMiddleware(RequestDelegate next) => _next = next;

    public async Task InvokeAsync(HttpContext context, ILogger<DiggTraceabilityMiddleware> logger)
    {
        var correlationId = context.Request.Headers["X-Correlation-ID"].FirstOrDefault()
                            ?? System.Diagnostics.Activity.Current?.TraceId.ToString()
                            ?? Guid.NewGuid().ToString();

        // Lägg till i logg-scopet så det indexeras i Elastic/Seq
        using (logger.BeginScope(new Dictionary<string, object> { ["CorrelationId"] = correlationId }))
        {
            context.Response.OnStarting(() =>
            {
                context.Response.Headers.TryAdd("X-Correlation-ID", correlationId);
                return Task.CompletedTask;
            });

            await _next(context);
        }
    }
}


2. Standardiserad Felhantering: Välkommen RFC 9457

Tiden då varje API hade sitt eget unika felformat är förbi. Digg kräver nu att fel returneras enligt RFC 9457 (som ersätter den äldre RFC 7807), med Content-Type application/problem+json.

Implementering i C#

ASP.NET Core har inbyggt stöd via ProblemDetails. Om du behöver hantera valideringsfel och möta profilen perfekt (som vill ha en specifik array för ogiltiga parametrar), gör du så här:

[ApiController]
[Route("v{version:apiVersion}/[controller]")]
public class AnsokningarController : ControllerBase
{
    [HttpPost]
    public IActionResult SkapaAnsokan([FromBody] AnsokanDto request)
    {
        if (request.Personnummer.Length != 12)
        {
            var problem = new ProblemDetails
            {
                Type = "https://api.dataportal.se/errors/valideringsfel",
                Title = "Felaktigt indata i förfrågan",
                Status = StatusCodes.Status400BadRequest,
                Detail = "Fältet 'personnummer' har felaktigt format.",
                Instance = HttpContext.Request.Path
            };

            // DIGG-specifikt tillägg för valideringsfel
            problem.Extensions.Add("invalid-params", new[]
            {
                new { name = "personnummer", reason = "Måste bestå av 12 siffror" }
            });

            return BadRequest(problem);
        }
        return Ok();
    }
}


3. Ordning och reda: Namngivning och “Samlingar”

I profilens senaste uppdateringar har url-strukturer stramats åt avsevärt för att tvinga fram förutsägbarhet:

  1. Samlingar är alltid plural: Det heter /kunder, inte /kund.
  2. Strikt Kebab-case: Flerordsresurser måste separeras med bindestreck, t.ex. /beviljade-ansokningar. Inget camelCase eller snake_case i URL:er.
  3. Endast Major-version i URL:en: Semantisk versionering gäller. Minor/Patch (som är bakåtkompatibla) ska inte ändra URL:en.

I .NET hanterar vi enklast detta med paketet Asp.Versioning.Mvc:

// Accepteras av profilen (GET /v2/kunder/123/bestallningar)
[ApiVersion("2.0")]
[Route("v{version:apiVersion}/kunder")]
public class KunderController : ControllerBase
{
    [HttpGet("{id}/bestallningar")]
    public IActionResult GetBestallningar(int id) { ... }
}


4. UUIDv7: En räddare i nöden för dina databaser

En detalj i profilen som kan verka liten, men som har enorm arkitektonisk påverkan, är uppdateringen av IETF-standarder. Standarden för unika identifierare pekar nu på RFC 9562.

Detta innebär att vi officiellt uppmuntras att sluta använda UUIDv4 (helt slumpmässiga GUIDs) och istället använda UUIDv7.

Varför är detta viktigt? Slumpmässiga GUIDs skapar massiv indexfragmentering i relationsdatabaser (som SQL Server). UUIDv7 kombinerar en tidsstämpel i början med slumpmässighet på slutet. De är sekventiella, vilket gör att databasen kan sortera dem effektivt, samtidigt som de förblir globalt unika och säkra att exponera externt. I .NET 10 och nyare Entity Framework-versioner finns det fantastiskt stöd för att generera dessa direkt.


5. Goodbye XML, Hello JSON

Profilen förordar nu starkt application/json (med UTF-8 som självklar standard). Stödet för XML har degraderats till ett valfritt KAN-krav. För att säkerställa att ditt .NET-API inte av misstag returnerar något annat, och för att tvinga fram camelCase enligt profilens rekommendation, lägger du till detta i din konfiguration:

builder.Services.AddControllers(options =>
{
    // Returnera 406 Not Acceptable om klienten envisas med XML
    options.ReturnHttpNotAcceptable = true;
})
.AddJsonOptions(options =>
{
    options.JsonSerializerOptions.PropertyNamingPolicy = JsonNamingPolicy.CamelCase;
});


Sammanfattning

Att följa DIGG:s REST API-profil v2.0.0 handlar inte bara om regelefterlevnad – det handlar om att bygga robusta, moderna och driftbara system. Genom att integrera distribuerad spårning från dag ett, använda RFC-standardiserad felhantering och låta UUIDv7 rädda dina databasindex, bygger du API:er som kommer att stå emot tidens tand.

Tips! När ditt API är klart, glöm inte att köra din OpenAPI-specifikation genom DIGG:s valideringstjänst (RAP-LP) för att dubbelkolla att du uppfyller alla SKALL-krav.

🔗 raplp.digg.se, RAP-LP (står för: REST API-profil Lint Processor)


Källor och Vidare Läsning

1. DIGG & Sveriges Dataportal

Dessa är de officiella riktlinjerna från Myndigheten för digital förvaltning (DIGG) som dikterar kraven för API-utveckling inom svensk offentlig sektor.

2. Microsoft & .NET-dokumentation

Officiell dokumentation för hur du implementerar de underliggande koncepten i moderna .NET-applikationer (C#).

3. IETF och W3C Standarder (RFC:er)

De internationella standarddokumenten som Diggs REST API-profil nu stöder sig på för att framtidssäkra offentlig sektors IT-infrastruktur.

4. Microsoft & OpenAPI (Specifikt för .NET 8, 9 och 10)

När det gäller OpenAPI (tidigare känt som Swagger) i .NET har det skett ett stort och viktigt skifte nyligen, vilket är högst relevant om du bygger för .NET 9 eller .NET 10.

Från och med .NET 9 har Microsoft fasat ut tredjepartsbiblioteket Swashbuckle som standard i sina mallar, och istället byggt in ett eget, fullt integrerat (och snabbare) stöd för OpenAPI direkt i ramverket via paketet Microsoft.AspNetCore.OpenApi.


Ett hett tips: Eftersom Digg:s Lint-verktyg kräver en väldigt exakt utformad OpenAPI-specifikation, är de nya “Transformers” i .NET 10 ovärderliga. De låter dig injicera globala regler (t.ex. att Content-Type: application/problem+json alltid är standard för 400- och 500-svar) direkt i C#-koden, så att din specifikation alltid är perfekt synkad med din kod och går igenom RAP-LP-valideringen utan anmärkning!