Inbäddat flöde (iframe)
Bädda in identitets- och kreditkontroll direkt på din egen sida. Användaren identifierar sig med BankID utan att lämna sidan,
du får direkt informationen via postMessage och du kan hämta hela kreditupplysningen via vårt api.
Översikt
När passar det inbäddade flödet?
Det inbäddade flödet är ett alternativ till SMS-,Kivra- och brevflödet i POST /api/v1/check.
Du anger ingen mottagare i förväg — istället bäddar du in en iframe där användaren själv identifierar sig
med BankID. Vid lyckad autentisering genomförs identitets- och kreditkontroll och resultatet rapporteras tillbaka. Du får
automatiskt alla uppgifter du behöver till lägsta möjliga kostnad.
Bra att veta
- Du får både ett kompakt och enkelt svar med identitetsuppgifter via javascript och kan hämta hela kreditupplysningen via vårt API (utan ytterligare kostnad).
- Levereras med
deliveryMethod = "embed"i webhook-payload och API-svar. - Stöds inte i testläge — tenant måste vara validerad och köra skarpt.
- Användaren får alltid sin omfrågekopia via Mina sidor.
Aktivera inbäddat flöde
Två steg i portalen.
1. Slå på flödet
Gå till Inställningar → Inbäddat flöde (iframe) och bocka i Aktivera inbäddat flöde. Vi skapar automatiskt upp en säker integration för ditt konto som krävs för att iframen ska fungera — ingen extra konfiguration behövs från din sida.
2. Lägg till tillåtna sidor
Under Tillåtna sidor (frame-ancestors) lägger du till de origins där iframen får laddas.
En origin är schema + värdnamn + port — t.ex. https://www.dindomän.se eller
https://butik.dindomän.se:8443. Lägg till produktion och staging separat. Bara exakta origins
matchas — wildcards stöds inte.
Origin-listan styr två saker samtidigt: vilka Content-Security-Policy: frame-ancestors som
skickas med iframens HTML-svar (browsern blockerar inläsning från andra sidor), och vilka Origin-headers
TIC accepterar på efterföljande BankID-anrop.
Integration på din sida
Minimal markup.
Snabbstart med SDK (rekommenderas)
Drop-in JS-bibliotek som hanterar iframe-skapande, origin-validering, höjd-auto-resize och postMessage-routing.
Alla callbacks är valfria. Returnerar ett objekt med .destroy() för att ta bort iframen.
<div id="credit-embed"></div>
<script src="https://credit.tic.io/js/tic-credit-embed.js"></script>
<script>
const session = TicCredit.embed({
slug: '{slug}',
container: '#credit-embed', // CSS selector eller Element
// Alla callbacks är valfria
onReady: () => { /* iframen är laddad */ },
onStarted: () => { /* användaren klickade på BankID-knappen */ },
onCompleted: (data) => {
// data.version — wire-format version (1)
// data.type — "tic-credit:completed"
// data.checkId — Guid
// data.personalIdentityNumber — 12 siffror
// data.givenName, data.surname — Tilltalsnamn + Efternamn från SPAR
// data.creditScore — int eller null (högre = bättre)
// data.folkbokforingsadress — { careOf, utdelningsadress1, utdelningsadress2, postNr, postort } eller null
// data.ipRisk — null, eller objekt:
// {
// level: "low" | "moderate" | "high" | "unknown",
// consentIp: null eller {
// ipAddress, // IP-adress
// countryCode, // ISO 3166 alpha-2
// countryName, // landets fulla namn
// usageType, // "Fixed Line ISP" | "Commercial" | "Data Center" | "VPN" | ...
// confidenceScore, // 0–100, Konfidens (högre = sämre rykte)
// isTor, // bool — Tor-utgångsnod
// isWhitelisted, // bool — manuellt whitelistad
// totalReports // antal abuse-rapporter
// },
// deviceIp: null eller samma form som consentIp
// }
// consentIp/deviceIp är var för sig null när den IP:n inte var publik (t.ex. localhost i dev).
// data.openMinaSidorUrl — URL för Mina sidor-handover (öppna i target="_top")
},
onError: (err) => {
// err.code — t.ex. "timeout" | "bankid_failed" | "ineligible" | "report_unavailable"
// err.message — svensk text
},
onAborted: () => { /* användaren tryckte Avbryt */ },
onPhoneSaved: ({ phoneNumber }) => { /* mobilnummer registrerat (E.164) */ }
});
// Riv ner iframen + lyssnaren när ni inte längre behöver den
// session.destroy();
</script>
SDK:n hanterar automatiskt: iframe-skapande, validering av event.origin, kontroll av wire-format
version, höjd-auto-resize via tic-credit:resize, och routing av postMessage till rätt callback.
Ladda gärna SDK:n från https://credit.tic.io/js/tic-credit-embed.js direkt — då får ni alltid den senaste versionen.
Manuell integration
Om du föredrar att skriva markup och meddelandehanteringen själv, så här ser den minimala integrationen ut.
<iframe src="https://credit.tic.io/embed/{slug}"
width="480"
height="640"
sandbox="allow-scripts allow-same-origin allow-popups allow-popups-to-escape-sandbox allow-top-navigation-by-user-activation"
referrerpolicy="strict-origin"
title="Kreditupplysning"></iframe>
Ersätt {slug} med din tenant-slug (samma som i SMS-flödets URL). strict-origin
säkerställer att TIC kan validera Referer mot allowlistan vid första laddning.
Sandbox-flaggorna släpper igenom JavaScript (BankID-flödet behöver det), allow-popups-to-escape-sandbox
behövs för att öppna Mina sidor i en topplevel-flik.
Events
Manuell integration kräver att ni själva hanterar alla händelser, inklusive
tic-credit:resize som styr iframens höjd. Utan resize-hanteringen kommer iframen
antingen ha scrollbars eller tom luft beroende på vilken vy som är aktiv.
const iframe = document.querySelector('iframe');
window.addEventListener('message', (event) => {
if (event.origin !== 'https://credit.tic.io') return;
const msg = event.data;
if (msg?.version !== 1) return; // valideringsskydd
switch (msg.type) {
case 'tic-credit:resize':
// Auto-anpassa iframens höjd till innehållets höjd.
iframe.style.height = msg.height + 'px';
break;
case 'tic-credit:ready':
// iframen är laddad, BankID kan startas
break;
case 'tic-credit:started':
// användaren har klickat "Starta BankID"
break;
case 'tic-credit:completed':
// msg.checkId, msg.creditScore, msg.folkbokforingsadress, msg.ipRisk, ...
console.log('Klar:', msg.checkId, msg.creditScore);
break;
case 'tic-credit:phone-saved':
// användaren registrerade mobilnummer för notiser
console.log('Phone saved:', msg.phoneNumber);
break;
case 'tic-credit:error':
// msg.code för programmatisk hantering, msg.message för UI
console.warn('Fel:', msg.code, msg.message);
break;
case 'tic-credit:aborted':
// användaren avbröt
break;
}
});
postMessage-händelser
Vad iframen skickar till integrationssidan.
| type | När | Extra fält |
|---|---|---|
tic-credit:ready |
Iframen har laddats och är redo för användarinteraktion. | — |
tic-credit:started |
Användaren har klickat på BankID-knappen och autentisering har påbörjats. | — |
tic-credit:completed |
BankID lyckades, kreditupplysning är klar. | Se payload-fält nedan. |
tic-credit:error |
Något gick fel — användaren ser felmeddelandet i iframen. |
message (svensk text),
code (en av: "timeout", "bankid_failed", "bankid_start_failed", "ineligible", "report_unavailable", "network", "unknown") — använd för lokalisering eller branchning
|
tic-credit:aborted |
Användaren avbröt flödet (cancel-knapp). | — |
tic-credit:phone-saved |
Användaren registrerade ett mobilnummer för notifieringar i "Klart"-steget. | phoneNumber (E.164) |
tic-credit:resize |
Iframens innehållshöjd har ändrats. SDK:n applicerar detta automatiskt på iframe.style.height. |
height (int, pixlar) |
Validera alltid event.origin === 'https://credit.tic.io' innan du litar på meddelandets innehåll.
Resultatet finns även via webhook och GET /api/v1/check/{checkId} — postMessage är en kortare och enklare form
för att få realtidsuppdateringar i front-end.
tic-credit:completed — payload-fält
| Fält | Typ | Beskrivning |
|---|---|---|
checkId |
Guid | Unikt id för kreditupplysningen. |
personalIdentityNumber |
string | 12 siffror, utan separatorer. |
givenName |
string \| null | Tilltalsnamn från SPAR (med fallback till BankID). |
surname |
string \| null | Efternamn från SPAR (med fallback till BankID). |
creditScore |
int \| null | Högre = bättre. |
folkbokforingsadress |
objekt \| null |
Folkbokföringsadressen från SPAR.
{ careOf, utdelningsadress1, utdelningsadress2, postNr, postort }.
|
ipRisk |
objekt \| null | IP-risk. Se ipRisk-objektet nedan för struktur. |
openMinaSidorUrl |
string | Top-level URL för "Öppna Mina sidor"-handover (kortlivad, ~5 min). |
ipRisk-objektet
Utvärdering av (a) IP:n som initierade identitets- och kreditkollen och (b) IP:n där BankID-appen faktiskt slutförde autentiseringen.
| Fält | Typ | Beskrivning |
|---|---|---|
level |
string |
"low" · "moderate" · "high" ·
"unknown" (unknown = ingen publik IP kunde kontrolleras).
|
consentIp |
objekt \| null | Per-IP-fält (se nedan), eller null om iframens IP inte var publik (t.ex. localhost i dev). |
deviceIp |
objekt \| null | Per-IP-fält (se nedan), eller null om BankID-enhetens IP inte var publik. |
Per-IP-fält (consentIp, deviceIp)
| Fält | Typ | Beskrivning |
|---|---|---|
ipAddress |
string | IP-adressen som kontrollerades. |
countryCode |
string \| null | Tvåställig landskod, ISO 3166-1 alpha-2 (t.ex. "SE"). |
countryName |
string \| null | Landets fulla namn. |
usageType |
string \| null | T.ex. "Fixed Line ISP", "Commercial", "Data Center", "VPN". |
confidenceScore |
int (0–100) | Konfidens — högre = sämre rykte. |
isTor |
bool | true om IP:n är en känd Tor-utgångsnod. |
isWhitelisted |
bool | Manuellt whitelistad. |
totalReports |
int | Antal abuse-rapporter mot IP:n. |
Mina sidor — topplevel-handover
Varför inloggningen sker utanför iframen.
Konsumentens session på Mina sidor sätts som en cookie.
Inne i en iframe är cookies tredjepartskakor — Safari/iOS och flera moderna browsers blockerar dem som standard.
Lösningen är en topplevel-handover: efter avklarad BankID renderar iframen en länk
"Öppna Mina sidor" med target="_top".
Klick på länken öppnar https://credit.tic.io/embed/{slug}/open?h=… i toppfönstret,
cookien sätts som förstapartskaka mot credit.tic.io och användaren landar på Mina sidor inloggad.
URL:en innehåller en kortlivad (5 min), datacrypto-skyddad token som binder till exakt den embed-session
som just slutförts.
Du behöver inte göra något extra — länken visas automatiskt i iframen efter tic-credit:completed.
completed-eventet inkluderar också openMinaSidorUrl om du föredrar att rendera knappen
i din egen UI istället för i iframen.
Mobilnummer-registrering i "Klart"-steget
Frivilligt opt-in för SMS-notiser om framtida omfrågekopior via Mina sidor.
När användaren har slutfört BankID-autentiseringen visas ett valfritt fält där personen kan ange sitt mobilnummer för att få SMS-notiser nästa gång någon genomför en identitets- och kreditkontroll på personen.
Om användaren redan har ett bekräftat nummer registrerat förifylls fältet och knappen byter till "Uppdatera".
En lyckad registrering skickar tic-credit:phone-saved till integrationssidan.
completed-eventet innehåller också existingPhoneNumber och existingPhoneConfirmed
så att din egen UI kan veta om användaren redan hade ett nummer innan iframen laddades.
Idempotens på /collect
Skydd mot dubbletter och misstag
Om JavaScripten i iframen råkar göra ett retry på /bankid/collect efter en nätverksstörning
(till exempel om fetch:en kraschar mellan att servern har svarat och svaret hinner deserialiseras)
upptäcker servern att sessionen redan är i statusen Completed och returnerar samma resultat-payload
som första gången — utan att köra eligibility-kontroll, IP-renommé, kreditupplysning eller debiteringsräkning igen.
Det betyder: din integration är säker att retry:a vid transienta fel utan risk för dubbeldebitering eller dubbla
kreditupplysningar. Samma checkId returneras varje gång.
Säkerhetsmodell
Vad som hindrar missbruk.
-
Origin-allowlist. Endast sidor du själv har lagt till i portalen får bädda in iframen.
Browsern blockerar laddning från andra sidor via
Content-Security-Policy: frame-ancestors; TIC blockerar dessutom alla efterföljande BankID-anrop varsOrigin-header inte matchar den som registrerades vid iframens första laddning. -
HMAC-signerad embed-token. Vid varje iframe-laddning genereras en HMAC-token bunden till
(embedSessionGuid, tenantId, exp)och signerad med din tenant-specifika hemlighet. Token följer med varje BankID-anrop (start, poll, collect, abort) och kan inte återanvändas över sessioner. Endast en SHA-256-hash av token sparas. -
Per-session BankID. En session kan utföra som mest en BankID-autentisering
och som mest en kreditupplysning. Efter lyckad collect växlar status till
Completedoch sessionen kan inte längre starta nya förfrågningar. - Eligibility-kontroll. Vid collect kör TIC samma eligibility-check som SMS-flödet — skyddade personuppgifter, avregistrerade och eventuell ID-skydd blockeras innan identitets- och kreditkontroll genomförs. Du debiteras inte för blockerade upplysningar.
- Inget testläge. Embed-flödet kan inte användas i testläge.
Sessionens livscykel
Statusövergångar för en session.
| Status | Innebörd |
|---|---|
Pending |
Iframen har laddats. BankID är ännu inte startad. |
Authenticating |
BankID-autentisering pågår. |
Completed |
BankID lyckades och identitets- och kreditkontroll är skapad. CreditCheckId är ifyllt. |
Failed |
BankID misslyckades eller rapporten gick inte att hämta. |
Expired |
15 minuter har gått sedan iframen laddades utan att flödet slutfördes. |
Aborted |
Användaren klickade Avbryt. |
Felhantering
Vanliga fel och vad de betyder.
| HTTP / kod | Orsak | Åtgärd |
|---|---|---|
404 Not Found vid GET /embed/{slug} |
Tenant finns inte, är inaktiv, eller har inte aktiverat embed-flödet. | Kontrollera slug och att Aktivera inbäddat flöde är ikryssat i portalen. |
403 Forbidden |
Sidan som försöker bädda in iframen finns inte i origin-allowlistan. | Lägg till exakt origin (schema + värd + port) i portalens Tillåtna sidor. |
400 + code: "ineligible" |
Användaren har skyddade uppgifter, är avregistrerad eller har konsumentspärr. | Visas i iframens egen UI. Användaren får inte belastas — du faktureras inte heller. |
502 + code: "report_unavailable" |
BankID lyckades men kreditupplysningens datakälla svarade inte. | Be användaren försöka igen senare. CreditCheck markeras som Failed. |
401 Unauthorized vid POST |
Embed-token saknas, är förfalskad eller har gått ut (15 min). | Ladda om iframen. Sidan måste komma från en allowlistad origin. |
Webhook och API-utdata
Hur embed-checks dyker upp i ditt befintliga flöde.
En kreditupplysning skapad via embed-flödet är en helt vanlig CreditCheck-rad — den följer samma
livscykel som SMS- och portal-flödet, dyker upp i portalens dashboard, finns tillgänglig
via GET /api/v1/check/{guid}, och triggar samma credit.completed-webhook.
Den enda skillnaden är fältet deliveryMethod:
{
"event": "credit.completed",
"checkId": "f3c2b3a1-...",
"deliveryMethod": "embed",
"personalNumber": "198001011234",
"creditScore": 720,
...
}
Använd fältet om du vill märka upp dessa upplysningar separat i din egen backend — annars behöver du inte tänka på skillnaderna.