Är du privatperson? Mina sidor

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ällningarInbä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ältTypBeskrivning
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ältTypBeskrivning
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ältTypBeskrivning
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 vars Origin-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 Completed och 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.