SweKit - Swedish validators
Swedish personnummer, orgnr, bankgiro, OCR, account to IBAN and bank days as a read-only remote MCP server.
Hosted MCP Server
npx add-mcp 'https://swekit-api.zenith-ops.workers.dev/mcp'Installs into Claude Code, Codex, Cursor and more
Documentation
Conventions
- Validators return
{"valid": bool, "errors": [codes]}plus parsed fields. HTTP 200 even if the number is invalid; HTTP 400 only for missing/malformed parameters. - Errors:
{"error":{"code","message"}}. Rate limit: HTTP 429 withRetry-After. - Response header
X-Plan: free | pro | gateway. - POST example:
curl -X POST https://swekit-api.zenith-ops.workers.dev/v1/personnummer -H 'content-type: application/json' -d '{"value":"811218-9876"}'
Access & limits
Anonymous demo: 20 requests/min/IP. Higher limits: send X-API-Key: <license key> (600 req/min). Marketplace subscribers use the marketplace's own key and quota. Pro key: contact the operator; pricing is not published.
curl examples
curl "https://swekit-api.zenith-ops.workers.dev/v1/personnummer?value=811218-9876"
curl -X POST "https://swekit-api.zenith-ops.workers.dev/v1/personnummer" -H 'content-type: application/json' -d '{"value":"811218-9876"}'
curl -H 'X-API-Key: YOUR_KEY' "https://swekit-api.zenith-ops.workers.dev/v1/account?clearing=7507&account=1211203"
# error response (missing parameter)
curl "https://swekit-api.zenith-ops.workers.dev/v1/orgnr"
{"error":{"code":"missing_parameter","message":"Missing parameter: value"}}
Error codes
| HTTP | Code | Meaning |
|---|---|---|
| 400 | missing_parameter | Required input was not supplied |
| 400 | bad_base | OCR base is invalid |
| 400 | bad_year | Year must be 1900–2200 |
| 400 | bad_date | Date must be YYYY-MM-DD |
| 400 | bad_input | Business-day input is invalid or out of range |
| 400 | invalid_json | POST body is not valid JSON |
| 401 | invalid_api_key | API key is invalid or expired |
| 429 | rate_limited | Per-minute quota exceeded |
| 500 | internal_error | Unexpected server error |
MCP client configuration
Claude Desktop (claude_desktop_config.json):
{"mcpServers":{"swekit":{"command":"npx","args":["mcp-remote","https://swekit-api.zenith-ops.workers.dev/mcp"]}}}
Cursor:
{"mcpServers":{"swekit":{"url":"https://swekit-api.zenith-ops.workers.dev/mcp"}}}
VS Code (.vscode/mcp.json):
{"servers":{"swekit":{"type":"http","url":"https://swekit-api.zenith-ops.workers.dev/mcp"}}}
MCP server
Remote MCP endpoint https://swekit-api.zenith-ops.workers.dev/mcp (POST JSON-RPC 2.0: initialize, tools/list, tools/call). Tools: validate_personnummer, validate_orgnr, validate_bankgiro, validate_plusgiro, validate_ocr, generate_ocr, swedish_account_to_iban, validate_iban, lookup_clearing_number, swedish_holidays, swedish_date_info, add_business_days, count_business_days.
Semantics worth knowing
- Bank accounts: checksum rules per Bankgirot (type 1 variants 1-2 mod-11; type 2 variants 1/3 mod-10, 2/4 mod-11). Swedbank 8xxx accounts are mod-10 "as a rule" and require the 5th clearing digit for IBAN. Plusgiro cannot be converted to IBAN. Some old accounts do not pass checksums.
- Business days (bank mode): Saturdays, Sundays, public holidays plus midsommarafton, julafton and nyårsafton are not business days (these are equated with Sundays for payment deadlines under Swedish law). Use
mode=workfor plain weekday-minus-red-day logic. Check your own contracts for company-specific rules. - Personnummer: age and century are inferred from the separator (
+= 100+). Gender is from the 9th digit (registered legal sex). Use for validation, not identification.
FAQ
Does a valid number prove an account or person exists?
No. The API checks syntax, dates and checksums only; it is not an identity, ownership or account-existence service.
Are requests stored?
No request data is stored by the service. Use POST for personal numbers so they do not appear in URLs or access logs.
Can I convert Plusgiro to IBAN?
No. Swedish bank accounts can be converted when their clearing range is known; Plusgiro is not a bank account format.
What are the limits?
Anonymous access is 20 requests/minute/IP. A valid Pro key allows 600 requests/minute/key. Pro key: contact the operator; pricing is not published.
Endpoints
GET /v1/personnummer
Validate & parse a Swedish personnummer / samordningsnummer
value | string | Personnummer in any common format (YYMMDD-NNNC, YYYYMMDDNNNC, with + for 100+). Prefer POST JSON {"value": "..."} so the number never appears in a URL. |
|---|
curl "https://swekit-api.zenith-ops.workers.dev/v1/personnummer?value=811218-9876&at=2026-10-16"
GET /v1/orgnr
Validate organisationsnummer, derive legal form and Swedish VAT number (SE#########01)
value | string | Org no. like 556036-0793, 5560360793, SE556036079301 |
|---|
curl "https://swekit-api.zenith-ops.workers.dev/v1/orgnr?value=556036-0793"
GET /v1/bankgiro
Validate bankgiro number (Luhn) and format it
value | string | 7-8 digits, with or without dash |
|---|
curl "https://swekit-api.zenith-ops.workers.dev/v1/bankgiro?value=5402-9681"
GET /v1/plusgiro
Validate plusgiro number
value | string | 2-8 digits |
|---|
curl "https://swekit-api.zenith-ops.workers.dev/v1/plusgiro?value=4-8"
GET /v1/ocr/validate
Validate an OCR / payment reference (Luhn check digit, optional length digit)
value | string | OCR digits |
|---|
curl "https://swekit-api.zenith-ops.workers.dev/v1/ocr/validate?value=12351"
GET /v1/ocr/generate
Generate an OCR reference from a base number
base | string | Digits, e.g. invoice number |
|---|---|---|
length_digit | boolean | Add length digit (default false) |
curl "https://swekit-api.zenith-ops.workers.dev/v1/ocr/generate?base=123&length_digit=true"
GET /v1/account
Validate a Swedish bank account (clearing + account, per Bankgirot rules) and convert to IBAN
number | string | Full account digits (clearing first), OR |
|---|---|---|
clearing | string | Clearing number (4 digits; 5 for Swedbank 8xxx) |
account | string | Account number without clearing |
curl "https://swekit-api.zenith-ops.workers.dev/v1/account?clearing=7507&account=1211203"
GET /v1/iban
Validate any IBAN (ISO 13616 mod-97, country length) and identify Swedish banks
value | string | IBAN, spaces allowed |
|---|
curl "https://swekit-api.zenith-ops.workers.dev/v1/iban?value=SE45 5000 0000 0583 9825 7466"
GET /v1/bic
Validate BIC/SWIFT format
value | string | 8 or 11 characters |
|---|
curl "https://swekit-api.zenith-ops.workers.dev/v1/bic?value=ESSESESS"
GET /v1/clearing
Look up bank, BIC, IBAN id and account type for a clearing number
value | string | First 4 digits of the account number |
|---|
curl "https://swekit-api.zenith-ops.workers.dev/v1/clearing?value=8327"
GET /v1/holidays
Swedish public holidays and eves for a year
year | integer | 1900-2200 (default: current year) |
|---|
curl "https://swekit-api.zenith-ops.workers.dev/v1/holidays?year=2026"
GET /v1/date
Info about a date: weekday (sv/en), ISO week, holiday names, business-day status
date | string | YYYY-MM-DD |
|---|---|---|
mode | string | "bank" (default; midsommarafton, julafton, nyårsafton also excluded) or "work" |
curl "https://swekit-api.zenith-ops.workers.dev/v1/date?date=2026-12-24"
GET /v1/business-days/add
Add (or subtract) N business days to a date
date | string | YYYY-MM-DD |
|---|---|---|
days | integer | Positive or negative, |n| <= 3650 |
mode | string | bank (default) or work |
curl "https://swekit-api.zenith-ops.workers.dev/v1/business-days/add?date=2026-12-22&days=2"
GET /v1/business-days/between
Count business days between two dates
from | string | YYYY-MM-DD |
|---|---|---|
to | string | YYYY-MM-DD |
mode | string | bank (default) or work |
curl "https://swekit-api.zenith-ops.workers.dev/v1/business-days/between?from=2026-10-16&to=2026-11-16"
Data sources
- Bankgirot, Bankernas kontonummer, 2024-02-22.
- Bankinfrastruktur i Sverige AB, IBAN and Swedish national account number page (clearing table, data date 2026-10-16).
- Holidays: computed (Meeus/Jones/Butcher Easter algorithm + statutory rules).