API-dokumentation

Introduktion

PiiSweep API ger dig programmatisk tillgång till PII-detektering och sanering av svensk text. Alla anrop går mot följande bas-URL:

https://piisweep.com/api/v1

API:et erbjuder två endpoints: en för att ta bort PII ur text och en för att enbart detektera PII utan att modifiera texten.

Autentisering

Alla API-anrop kräver en giltig API-nyckel som skickas i x-api-key headern. Du kan skapa och hantera dina nycklar i din dashboard.

API-nycklar har formatet pg_live_... och är unika för varje projekt. Dela aldrig din nyckel offentligt.

curl https://piisweep.com/api/v1/strip \ -H "x-api-key: pg_live_din_nyckel_här"

POST /v1/strip

Tar emot text, identifierar personuppgifter (PII) och returnerar en sanerad version där all PII har ersatts med platshållare.

Det valfria fältet types begränsar vilka PII-typer som detekteras. Möjliga värden: personnummer, coordination_number, reserve_number, org_number, hsa_id, phone, email, name. Om fältet utelämnas detekteras alla typer.

Det valfria fältet indexed (default false) suffixar platshållarna per typ — [NAME_1], [NAME_2], [PHONE_1] osv. Samma entitet på flera ställen i texten får samma index, så att en LLM som läser den sanerade texten kan referera tillbaka till en specifik person eller kontaktuppgift. Indexet finns även i detections[].placeholder så att du kan bygga en lookup tillbaka till originalvärdena.

Request body

{ "text": "string", // 1–100 000 tecken "types": ["personnummer", ...], // valfritt, default: alla "indexed": false // valfritt, suffixar platshållarna ([NAME_1], [NAME_2]...) }

Response

{ "original_length": 142, "stripped_length": 127, "stripped_text": "Kontakta [NAME] på [EMAIL]", "detections": [ { "type": "name", "original": "Erik Svensson", "placeholder": "[NAME]" } ], "processing_time_ms": 12 }

Exempel

curl -X POST https://piisweep.com/api/v1/strip \ -H "Content-Type: application/json" \ -H "x-api-key: pg_live_din_nyckel_har" \ -d '{"text": "Ring Erik Svensson på 070-123 45 67"}'

POST /v1/detect

Identifierar personuppgifter (PII) i texten utan att modifiera den. Användbar för att kontrollera om text innehåller känslig information innan den behandlas vidare.

Stöder samma valfria types och indexed som /v1/strip.

Request body

{ "text": "string", // 1–100 000 tecken "types": ["personnummer", ...], // valfritt, default: alla "indexed": false // valfritt, suffixar platshållarna ([NAME_1], [NAME_2]...) }

Response

{ "original_length": 142, "detections": [ { "type": "phone", "original": "070-123 45 67", "placeholder": "[PHONE]" } ], "pii_found": true, "processing_time_ms": 8 }

Exempel

curl -X POST https://piisweep.com/api/v1/detect \ -H "Content-Type: application/json" \ -H "x-api-key: pg_live_din_nyckel_har" \ -d '{"text": "Mitt personnummer är 199001011234"}'

POST /v1/restore — round-trip till AI och tillbaka

Det vanligaste flödet i AI-i-vården: skicka anonymiserad text till en LLM (OpenAI, Claude, ...) och sätt sedan tillbaka de riktiga namnen i svaret innan du visar det för klinikern. PiiSweep löser det med en session_id.

1. Strippa med session_id

Skicka in en valfri session_id (UUID) så lagras platshållare→original krypterat på vår sida. Indexerade platshållare aktiveras automatiskt så samma entitet får samma suffix. TTL kan styras med vault_ttl_seconds (60 till 604 800, default 86 400 = 24h).

curl -X POST https://piisweep.com/api/v1/strip \
  -H "x-api-key: pg_live_..." \
  -H "Content-Type: application/json" \
  -d '{
    "text": "Patient Anna Andersson har ont i ryggen.",
    "session_id": "550e8400-e29b-41d4-a716-446655440000"
  }'

Svaret innehåller en vault -indikator så du vet att lagringen lyckades:

{
  "stripped_text": "Patient [NAME_1] har ont i ryggen.",
  "detections": [...],
  "vault": { "stored": true, "expires_at": "2026-05-02T16:00:00Z" }
}

2. Skicka till LLM

Skicka stripped_text till valfri AI-modell. Inga personuppgifter lämnar vården. AI:n arbetar med platshållarna och refererar tillbaka till dem (t.ex. [NAME_1]) i sitt svar.

3. Återställ med /v1/restore

curl -X POST https://piisweep.com/api/v1/restore \
  -H "x-api-key: pg_live_..." \
  -H "Content-Type: application/json" \
  -d '{
    "text": "Föreslå rehab-program för [NAME_1].",
    "session_id": "550e8400-e29b-41d4-a716-446655440000"
  }'

Svar:

{
  "restored_text": "Föreslå rehab-program för Anna Andersson.",
  "restored": ["[NAME_1]"],
  "unrestored": [],
  "processing_time_ms": 12
}

Platshållare som inte finns i vaulten (utgångna eller aldrig sparade) lämnas orörda och rapporteras under unrestored. Originaldatat lagras AES-256-GCM-krypterat och raderas automatiskt när TTL löper ut.

Felkoder

Alla felmeddelanden returneras i följande format:

{ "error": { "code": "VALIDATION_ERROR", "message": "Text is required and must be 1-100000 characters" } }
KodMeddelandeBeskrivning
400VALIDATION_ERROROgiltig request body. Kontrollera att texten är mellan 1 och 100 000 tecken.
401UNAUTHORIZEDOgiltig eller saknad API-nyckel. Kontrollera att headern x-api-key är korrekt.
429RATE_LIMITEDFör många anrop. Vänta och försök igen, se Retry-After headern.
500INTERNAL_ERRORServerfel. Försök igen senare eller kontakta support om problemet kvarstår.

Rate limits

API:et tillåter 1 000 anrop per minut per API-nyckel. Varje svar innehåller följande headers för att hjälpa dig hantera dina anrop:

HeaderBeskrivning
X-RateLimit-LimitMaximalt antal anrop per minut.
X-RateLimit-RemainingAntal återstående anrop i nuvarande fönstret.
Retry-AfterAntal sekunder att vänta innan nästa anrop (visas vid 429-svar).

Custom ordlista

Varje API-nyckel kan ha en egen ordlista med allow- och deny-regler som skriver över standarddetektionen. Lägg till regler i dashboarden eller via API:et nedan. Hantering räknas inte mot din kvot.

allow

Termen lämnas alltid orörd. Använd för organisationsnamn, varumärken eller domänspecifika uttryck som annars riskerar att redigeras som namn (t.ex. Region Stockholm).

deny

Termen redigeras alltid, även om ingen detektor skulle matchat den. Använd för ovanliga namn, intern jargong eller känsliga begrepp som måste döljas oavsett.

Företrädesregel: deny vinner. Om samma term finns på båda listorna blir den redigerad. Termjämförelse är skiftlägesokänslig och Unicode-medveten (svenska tecken funkar fint).

GET /v1/dictionary

Listar alla regler kopplade till nyckeln.

curl https://piisweep.com/api/v1/dictionary \
  -H "x-api-key: pg_live_..."

POST /v1/dictionary

Lägger till en regel. type är valfri — utan typ exempterar/redigerar regeln oavsett detekterad typ (deny utan typ defaultar till name).

curl -X POST https://piisweep.com/api/v1/dictionary \
  -H "x-api-key: pg_live_..." \
  -H "Content-Type: application/json" \
  -d '{
    "term": "Region Stockholm",
    "kind": "allow"
  }'

DELETE /v1/dictionary/:id

curl -X DELETE https://piisweep.com/api/v1/dictionary/<id> \
  -H "x-api-key: pg_live_..."

PII-typer

Följande typer av personuppgifter detekteras och ersätts med motsvarande platshållare. Med indexed: true blir platshållarna numrerade per typ — [NAME_1], [NAME_2] osv.

TypPlatshållareAnmärkning
personnummer[PERSONAL_NUMBER]Svenska personnummer (10/12-siffrigt). Luhn-validering för bara siffror, plausibelt datum för formatet med bindestreck.
coordination_number[COORDINATION_NUMBER]Samordningsnummer (dag + 60). Detekteras separat från personnummer för audit-spårning.
reserve_number[RESERVE_NUMBER]Reservnummer för oidentifierade patienter. Kräver markörord (reservnummer, reservnr, tillfälligt personnummer) inom 60 tecken före numret.
org_number[ORG_NUMBER]Svenskt organisationsnummer (10-siffrigt, Luhn-validerat). Tredje siffran ≥ 2 särskiljer från personnummer.
hsa_id[HSA_ID]HSA-id (Inera) — identifierare för svenska vårdgivare och vårdpersonal. Format SE<10-13 siffror>-<alfanumerisk svans>.
phone[PHONE]Mobil- och fastnätsnummer i svenska format och +46.
email[EMAIL]E-postadresser i alla vanliga format.
name[NAME]Svenska för- och efternamn baserat på SCB:s namnstatistik plus heuristik för efternamnssuffix och kliniska kontexter.