Eksternt API
Hvordan integrere data fra eksterne API-er i Altinn-applikasjonen din.
Introduksjon
Et Eksternt API lar deg integrere data fra eksterne API-er i Altinn-applikasjonen din. Dette er nyttig når du trenger å vise eller behandle data fra eksterne kilder i applikasjonen din. Dette fungerer ved å implementere grensesnittet IExternalApiClient
og registrere implementasjonen i applikasjonens tjenestebeholder. Når den er implementert, kan dataene fra det eksterne API-et nås gjennom uttrykk (se dokumentasjonen for uttrykk) eller i andre klasser i applikasjonen din.
Hvordan det fungerer
For å bruke funksjonen for Eksternt API, må du:
- Opprette en klasse som implementerer grensesnittet
IExternalApiClient
- Registrere implementasjonen i filen
Program.cs
underRegisterCustomAppServices
Grensesnittet IExternalApiClient
krever at du implementerer:
- En
Id
-egenskap som unikt identifiserer din eksterne API-klient - En
GetExternalApiDataAsync
-metode som returnerer dataene fra det eksterne API-et
Metoden GetExternalApiDataAsync
kan returnere et hvilket som helst objekt (men ikke primitive typer), noe som lar deg strukturere de returnerte dataene etter dine behov.
Implementasjonseksempel
Her er et eksempel på hvordan du implementerer grensesnittet IExternalApiClient
:
App/logic/ExternalApiTestClient.cs
public class ExternalApiTestClient : IExternalApiClient
{
public string Id => "externalApiTestId";
public async Task<object> GetExternalApiDataAsync(
InstanceIdentifier instanceIdentifier,
Dictionary<string, string> queryParams = null
)
{
var mockData = new[]
{
new
{
schemaTitle = "Pantopplysninger for TRANBY OG RØDEBERG REGNSKAP",
href = "https://example.com/mock1",
date = DateTime.Now.ToString("dd.MM.yyyy")
},
new
{
schemaTitle = "Panteopplysninger for MADELENE NYRUD",
href = "https://example.com/mock2",
date = DateTime.Now.AddDays(-1).ToString("dd.MM.yyyy")
},
new
{
schemaTitle = "Panteopplysninger for MADELENE NYRUD",
href = "https://example.com/mock3",
date = DateTime.Now.AddDays(-2).ToString("dd.MM.yyyy")
},
new
{
schemaTitle = "Registerutskrift for TRANBY OG RØDEBERG REGNSKAP",
href = "https://example.com/mock3",
date = DateTime.Now.AddDays(-2).ToString("dd.MM.yyyy")
},
new
{
schemaTitle = "Registerutskrift for MADELENE NYRUD",
href = "https://example.com/mock3",
date = DateTime.Now.AddDays(-2).ToString("dd.MM.yyyy")
},
new
{
schemaTitle = "Ektepakt",
href = "https://example.com/mock3",
date = DateTime.Now.AddDays(-2).ToString("dd.MM.yyyy")
},
new
{
schemaTitle = "Registerutskrift fra Løseøreregisteret",
href = "https://example.com/mock3",
date = DateTime.Now.AddDays(-2).ToString("dd.MM.yyyy")
}
};
return mockData;
}
}
I dette eksempelet returnerer vi testdata, men i en reell implementasjon ville du typisk bruke en HttpClient for å gjøre HTTP-forespørsler til et eksternt API.
Registrering av Eksternt API-klient
Etter å ha implementert grensesnittet IExternalApiClient
, må du registrere implementasjonen din i filen Program.cs
:
App/Program.cs
void RegisterCustomAppServices(IServiceCollection services, IConfiguration config)
{
// Registrer din eksterne API-klient
services.AddTransient<IExternalApiClient, ExternalApiTestClient>();
// Andre tilpassede tjenester
}
Bruk av data fra det Eksterne API-et i applikasjonen din
Funksjonen for Eksternt API er primært designet for å brukes gjennom uttrykk i Altinn-applikasjonen din. Dette lar deg vise data fra eksterne kilder eller implementere betinget logikk basert på eksterne data direkte i skjemaene og layoutene dine.
Tilgang til Eksternt API-data gjennom dynamiske uttrykk
For å få tilgang til data fra din eksterne API-klient i dynamiske uttrykk, kan du bruke funksjonen externalApi
. Denne funksjonen krever to parametere:
clientId
: ID-en til din eksterne API-klientpathToProperty
: Dotnotasjon til egenskapen du vil ha tilgang til fra det returnerte objektet
["externalApi", "externalApiTestId", "0.schemaTitle"]
Dette uttrykket vil returnere skjematittelen til det første elementet i lista som returneres av GetExternalApiDataAsync
-metoden til den eksterne API-klienten med ID-en “externalApiTestId”.
Parameteren pathToProperty
bruker punktnotasjon for å navigere gjennom objektstrukturen. For eksempel:
"0"
får tilgang til det første elementet i en liste"items.0.title"
får tilgang til tittel-egenskapen til det første elementet i items-lista"data.user.name"
får tilgang til name-egenskapen til user-objektet innenfor data-objektet
Eksempler på bruk av Eksternt API-data i uttrykk
Visning av eksterne data
Du kan bruke Eksternt API-data for å vise informasjon i skjemaet ditt:
{
"id": "externalDataText",
"type": "Text",
"textResourceBindings": {
"value": [
"concat",
"Dokumenttittel: ",
["externalApi", "externalApiTestId", "0.schemaTitle"]
]
}
}
Betinget synlighet basert på eksterne data
Du kan også bruke Eksternt API-data for å kontrollere synligheten til komponenter:
{
"id": "conditionalInput",
"type": "Input",
"hidden": ["equals", ["externalApi", "externalApiTestId", "length"], 0]
}
Dette vil skjule komponenten hvis det eksterne API-et returnerer en tom array.
For mer informasjon om uttrykk og hvordan du bruker dem i Altinn-applikasjonen din, se dokumentasjonen for dynamiske uttrykk.
Tilgang til data gjennom API-endepunktet
Dataene som hentes gjennom implementasjonen av Eksternt API er også tilgjengelige gjennom et REST API-endepunkt. Endepunktet følger dette mønsteret:
{org}/{app}/instances/{instanceOwnerPartyId:int}/{instanceGuid:guid}/api/external/{externalApiId}
Hvor:
{org}
er organisasjonskoden (f.eks. “ttd”){app}
er applikasjonsnavnet (f.eks. “my-app”){instanceOwnerPartyId:int}
er part-ID-en til instanseieren{instanceGuid:guid}
er den unike identifikatoren til instansen{externalApiId}
er ID-en til den eksterne API-klienten (verdien som returneres avId
-egenskapen)
For eksempel, for å få tilgang til “externalApiTestId” Eksternt API for en spesifikk instans, ville du bruke:
https://ttd.apps.altinn.no/ttd/my-app/instances/50001337/b2572673-5afa-4a23-9c4e-db2cb0f8a9c9/api/external/externalApiTestId
Du kan også sende spørreparametere til endepunktet, som vil bli videresendt til GetExternalApiDataAsync
-metoden:
https://ttd.apps.altinn.no/ttd/my-app/instances/50001337/b2572673-5afa-4a23-9c4e-db2cb0f8a9c9/api/external/externalApiTestId?param=value
Responsen vil være JSON-representasjonen av objektet som returneres av GetExternalApiDataAsync
-metoden.
Eksempel: Implementering av en reell Eksternt API-klient
Her er et mer komplett eksempel på en Eksternt API-klient som kaller et reelt API:
App/logic/WeatherApiClient.cs
public class WeatherApiClient : IExternalApiClient
{
private readonly HttpClient _httpClient;
private readonly ILogger<WeatherApiClient> _logger;
private readonly IConfiguration _configuration;
public WeatherApiClient(
HttpClient httpClient,
ILogger<WeatherApiClient> logger,
IConfiguration configuration)
{
_httpClient = httpClient;
_logger = logger;
_configuration = configuration;
// Konfigurer HTTP-klienten
_httpClient.BaseAddress = new Uri("https://api.weatherapi.com/v1/");
_httpClient.DefaultRequestHeaders.Add("Accept", "application/json");
}
public string Id => "weatherApi";
public async Task<object> GetExternalApiDataAsync(
InstanceIdentifier instanceIdentifier,
Dictionary<string, string> queryParams = null)
{
try
{
// Hent API-nøkkelen fra konfigurasjonen
var apiKey = _configuration["WeatherApi:ApiKey"];
if (string.IsNullOrEmpty(apiKey))
{
_logger.LogError("Weather API-nøkkel ikke funnet i konfigurasjonen");
return new { Error = "API-nøkkel ikke konfigurert" };
}
// Legg til API-nøkkel i header i stedet for spørrestreng for bedre sikkerhet
_httpClient.DefaultRequestHeaders.Add("X-Api-Key", apiKey);
// Bygg spørrestrengen
var query = new Dictionary<string, string>
{
{ "q", queryParams?.GetValueOrDefault("location") ?? "Oslo" },
{ "days", queryParams?.GetValueOrDefault("days") ?? "3" }
};
var queryString = string.Join("&", query.Select(kv => $"{kv.Key}={Uri.EscapeDataString(kv.Value)}"));
// Gjør API-kallet
var response = await _httpClient.GetAsync($"forecast.json?{queryString}");
// Sjekk om forespørselen var vellykket
if (response.IsSuccessStatusCode)
{
// Parse og returner responsen
var content = await response.Content.ReadAsStringAsync();
return JsonSerializer.Deserialize<JsonDocument>(content);
}
else
{
// Håndter feilrespons
var errorContent = await response.Content.ReadAsStringAsync();
_logger.LogError($"Weather API returnerte feil: {response.StatusCode}, {errorContent}");
return new { Error = $"Weather API returnerte feil: {response.StatusCode}" };
}
}
catch (Exception ex)
{
// Håndter unntak
_logger.LogError($"Feil ved kall til Weather API: {ex.Message}");
return new { Error = "Kunne ikke kalle Weather API" };
}
}
}
Registrer denne klienten i Program.cs
:
void RegisterCustomAppServices(IServiceCollection services, IConfiguration config)
{
// Registrer Weather API-klienten som IHttpClient
services.AddHttpClient<WeatherApiClient>();
// Registrer Weather API-klienten som IExternalApiClient
services.AddTransient<IExternalApiClient, WeatherApiClient>();
// Andre tilpassede tjenester
}
Eksempel: Bruk av Eksternt API med Maskinporten
For å bruke eksterne API-er som krever Maskinporten-autentisering, trenger du en Maskinporten-klient med tilgang til de nødvendige scopene for API-et du ønsker å integrere:
altinn:serviceowner
(hvis du er en tjenesteeier)- Eventuelle andre scopes som kreves av det spesifikke API-et du integrerer mot
For å sette opp dette kan du følge de generelle stegene i veiledningen for Maskinporten-integrasjon med noen modifikasjoner beskrevet nedenfor.
Eksternt API-klienten trenger en Maskinporten-klient for å kommunisere med beskyttede API-er. Konfigurasjonsobjektet ser typisk slik ut:
App/appsettings.json
"MaskinportenSettings": { "Authority": "https://[test.]maskinporten.no/", "ClientId": "din-klient-id", "JwkBase64": "base64-kodet-jwk" }
Hvis du trenger en annen konfigurasjonssti, kan du konfigurere den med hjelp av
ConfigureMaskinportenClient
:App/Program.cs
void RegisterCustomAppServices( IServiceCollection services, IConfiguration config, IWebHostEnvironment env ) { services.ConfigureMaskinportenClient( "DinUnikeMaskinportenSettingsSti" ); }
Du kan registrere Maskinporten-klienten på HttpClient-klassen som trenger dette i
Program.cs
ved å bruke extention-metodenUseMaskinportenAuthorisation
:App/Program.cs
void RegisterCustomAppServices( IServiceCollection services, IConfiguration config, IWebHostEnvironment env ) { services.AddHttpClient<WeatherApiClient>().UseMaskinportenAuthorisation("scope:1", "scope:2"); }
Hvis du trenger Maskinporten for autorisasjon mot en annen Altinn applikasjon, trenger du et Altinn-token. For å få det kan du bruke
UseMaskinportenAltinnAuthorisation
:App/Program.cs
void RegisterCustomAppServices( IServiceCollection services, IConfiguration config, IWebHostEnvironment env ) { services.AddHttpClient<WeatherApiClient>().UseMaskinportenAltinnAuthorisation("scope:1", "scope:2"); }
Sikkerhetshensyn
Når du implementerer en Eksternt API-klient, bør du vurdere følgende sikkerhetsaspekter:
Autentisering: Sørg for at din eksterne API-klient autentiserer riktig med det eksterne API-et. Dette kan innebære bruk av API-nøkler, OAuth-tokens eller andre autentiseringsmekanismer.
Databeskyttelse: Vær forsiktig med hvilke data du sender til og mottar fra det eksterne API-et. Unngå å sende sensitive data med mindre det er nødvendig, og valider alle innkommende data.
Feilhåndtering: Som vist i eksempelet ovenfor, håndter feil på en elegant måte for å forhindre at sensitiv informasjon eksponeres for sluttbrukere.
Ratebegrensning: Implementer ratebegrensning for å forhindre overbelastning av det eksterne API-et og for å overholde eventuelle bruksgrenser pålagt av API-leverandøren.
Feilsøking
Her er noen vanlige problemer du kan støte på når du implementerer Eksternt API og hvordan du løser dem:
Eksternt API-data vises ikke i brukergrensesnittet
Hvis dataene fra ditt eksterne API ikke vises i UI-komponentene dine:
- Sjekk implementasjonen din: Sørg for at
IExternalApiClient
-implementasjonen din returnerer dataen du forventer. - Verifiser registreringen: Sørg for at klienten din er riktig registrert i
Program.cs
. - Sjekk uttrykkene: Verifiser at uttrykkene dine refererer til riktig ID for den eksterne API-klienten og ritkig dotnotasjon til egenskapen du vil hente ut.
- Inspiser nettverksforespørsler: Bruk nettleserens utviklerverktøy for å sjekke om API-endepunktet blir kalt og hvilken respons det returnerer.
- Sjekk logger: Se etter eventuelle feil i applikasjonsloggene relatert til den eksterne API-klienten.
Autentiseringsproblemer med eksterne tjenester
Hvis du har problemer med å autentisere med eksterne tjenester:
- Sjekk legitimasjon: Verifiser at API-nøkler, tokens eller andre autentiseringverdier er korrekte og ikke utløpt.
- Inspiser forespørselsheadere: Sørg for at autentiseringsheadere er riktig satt i forespørslene dine.
- Sjekk miljø: Sørg for at du bruker riktige miljøinnstillinger (dev, test, prod) for den eksterne tjenesten.
- Verifiser scopes: For Maskinporten, sørg for at du har riktige scopes konfigurert for API-ene du prøver å få tilgang til.