Guide · Node.js · SDK · REST API

WKN Validation in Node.js

The Wertpapierkennnummer is Germany's native securities identifier — 6 alphanumeric characters, no check digit, embedded in every German ISIN. Here's how to validate WKNs correctly in Node.js and enrich them with live instrument data.

1. What is a WKN?

A WKN (Wertpapierkennnummer — also written WPKN or WPK) is a 6-character alphanumeric identifier assigned to securities traded in Germany. It has been used since 1968 and is issued by WM Datenservice (formerly Wertpapier-Mitteilungen), the Frankfurt-based financial data provider that acts as the National Numbering Agency (NNA) for German securities under ISO 6166.

WKNs appear in German brokerage confirmations, bank statements, and legacy trading systems. While ISINs have become the standard in cross-border and regulatory contexts (MiFID II, EMIR), WKNs remain widely used in the German retail and private banking segment. Many German financial APIs and data feeds still expose WKNs alongside or instead of ISINs.

Unlike ISIN, CUSIP, or SEDOL, the WKN has no check digit. It is a purely opaque sequence — there is no algorithm to verify whether a WKN is valid. The only way to confirm a WKN maps to a real security is to look it up in a reference database.


2. WKN anatomy

A WKN is exactly 6 characters long and consists of digits and uppercase letters:

PropertyDetail
Length6 characters
Allowed characters[A-Z0-9]
Check digitNone
Issuing authorityWM Datenservice, Frankfurt
ScopeGerman securities (equities, bonds, funds, warrants, ETFs)

Some well-known examples:

WKNISINSecurity
514000DE0005140008Deutsche Bank AG
716460DE0007164600SAP SE
723610DE0007236101Siemens AG
840400DE0008404005Allianz SE
ℹ️Historically WKNs were purely numeric. Alphanumeric WKNs (containing letters) were introduced later for structured products, warrants, and certificates. Both variants follow the same 6-character format and are equally valid.

3. WKN inside a German ISIN

German ISINs (country code DE) embed the WKN in a predictable way. The NSIN (National Securities Identifying Number) portion of a German ISIN is the WKN zero-padded on the left to 9 characters:

PartCharsExample
Country code1–2DE
NSIN (WKN padded to 9)3–11000514000
ISIN check digit128

For Deutsche Bank (WKN 514000):

DE  +  000514000  +  8  =  DE0005140008
      
DE   000514000 8    ISIN check digit (Luhn over expanded string)
    
          
country   WKN zero-padded to 9 chars

You can extract a WKN from a German ISIN by taking characters 5–10 (1-indexed): strip the leading zeros from the NSIN to recover the original WKN. If you already have a DE ISIN, pass it to /v0/isin instead of /v0/wkn.


4. Why format checks aren't enough

No check digit — any 6-char string passes format validation

Because WKN has no check digit, every 6-character alphanumeric string is structurally valid. A typo like 514001 instead of 514000 passes a regex check but refers to a completely different security — or no security at all. Without a database lookup, there is no way to detect the error.

Retired and reassigned WKNs

When a company is delisted, merges, or undergoes a corporate restructuring, its WKN may be retired or replaced. A structurally valid WKN might point to a company that no longer exists, a fund that was wound up, or a warrant that expired. Format validation cannot distinguish an active security from a retired one.

No public WKN registry

WM Datenservice does not publish a free, downloadable list of all valid WKNs. The database is a commercial product. Maintaining your own mapping table is impractical — an API backed by OpenFIGI is the standard alternative for applications that need to verify WKNs against real securities.

Alphanumeric vs. numeric — know your source system

Some legacy German banking systems pad WKNs with leading zeros to reach 6 digits, treating them as numeric codes. Others pass them without padding. If your data arrives with inconsistent formatting, normalise before validating: strip whitespace, uppercase, and ensure exactly 6 characters.


5. The right solution: one API call

The IsValid WKN API handles format validation and instrument lookup via OpenFIGI in a single GET /v0/wkn request. Because there is no check digit to compute, the value is entirely in the enrichment: confirming the WKN maps to a real security and surfacing its name, ISIN, exchange, and FIGI.

Format
Validation
6-char [A-Z0-9] check
Live
Enrichment
Name, ISIN, FIGI, exchange & more
100/day
Free tier
no credit card

Get your free API key at isvalid.dev. The free tier includes 100 calls per day.

Full parameter reference and response schema: WKN Validation API docs →


6. Node.js code example

Using the @isvalid-dev/sdk package or the native fetch API (Node 18+).

// wknValidator.js
import { createClient } from '@isvalid-dev/sdk';

const iv = createClient({ apiKey: process.env.ISVALID_API_KEY });

// ── Example usage ─────────────────────────────────────────────────────────────

const result = await iv.wkn('514000');  // Deutsche Bank AG

if (!result.valid) {
  console.log('Invalid WKN: wrong format (must be 6 alphanumeric characters)');
} else {
  console.log(`WKN         : ${result.wkn}`);
  if (result.found) {
    console.log(`Name        : ${result.name}`);
    console.log(`ISIN        : ${result.isin}`);
    console.log(`Ticker      : ${result.ticker}`);
    console.log(`Exchange    : ${result.exchCode}`);
    console.log(`FIGI        : ${result.figi}`);
    console.log(`Sector      : ${result.marketSector}`);
  }
}

Expected output for 514000:

WKN         : 514000
Name        : Deutsche Bank AG
ISIN        : DE0005140008
Ticker      : DBK
Exchange    : GY
FIGI        : BBG000BC5588
Sector      : Equity

In an Express.js route handler:

// routes/securities.js (Express)
app.get('/securities/validate-wkn', async (req, res) => {
  const { wkn } = req.query;

  if (!wkn) {
    return res.status(400).json({ error: 'Missing wkn parameter' });
  }

  let result;
  try {
    result = await validateWkn(wkn);
  } catch {
    return res.status(502).json({ error: 'WKN validation service unavailable' });
  }

  if (!result.valid) {
    return res.status(400).json({ error: 'Invalid WKN', wkn });
  }

  res.json({
    wkn: result.wkn,
    found: result.found ?? null,
    isin: result.isin ?? null,
    name: result.name ?? null,
    ticker: result.ticker ?? null,
    exchCode: result.exchCode ?? null,
    figi: result.figi ?? null,
  });
});
The API strips whitespace and uppercases input automatically — pass the raw value without pre-processing. Both 514 000 and 514000 are handled correctly.

7. cURL example

Deutsche Bank AG:

curl -H "Authorization: Bearer YOUR_API_KEY" \
  "https://api.isvalid.dev/v0/wkn?value=514000"

SAP SE:

curl -H "Authorization: Bearer YOUR_API_KEY" \
  "https://api.isvalid.dev/v0/wkn?value=716460"

Invalid format — fewer than 6 characters:

curl -H "Authorization: Bearer YOUR_API_KEY" \
  "https://api.isvalid.dev/v0/wkn?value=5140"

8. Understanding the response

Response for a valid WKN found in OpenFIGI:

{
  "valid": true,
  "wkn": "514000",
  "found": true,
  "dataSource": "openfigi",
  "isin": "DE0005140008",
  "name": "Deutsche Bank AG",
  "ticker": "DBK",
  "exchCode": "GY",
  "securityType": "Common Stock",
  "marketSector": "Equity",
  "figi": "BBG000BC5588",
  "compositeFIGI": "BBG000BC5588"
}

Response for a valid WKN not found in OpenFIGI:

{
  "valid": true,
  "wkn": "514000",
  "found": false
}

Response for an invalid WKN:

{
  "valid": false
}
FieldTypeDescription
validbooleanFormat validation result (6-char [A-Z0-9])
wknstringNormalised (uppercased, whitespace-stripped) WKN
foundboolean | nulltrue — found in OpenFIGI; false — not found; null — OpenFIGI unavailable
dataSourcestringAlways openfigi when present
isinstring | nullAssociated ISIN (e.g. DE0005140008); null if not returned
namestring | nullFull instrument name
tickerstring | nullExchange ticker symbol
exchCodestring | nullBloomberg exchange code (e.g. GY for XETRA)
securityTypestring | nullSecurity type (e.g. Common Stock)
marketSectorstring | nullMarket sector (e.g. Equity)
figistring | nullFinancial Instrument Global Identifier
compositeFIGIstring | nullComposite FIGI across all exchanges

9. Edge cases to handle

found: null vs. found: false

found: false means OpenFIGI was reachable but did not recognise the WKN. found: null means the lookup failed (timeout, rate limit, or network error). In the null case the WKN is still structurally valid — treat it as inconclusive and retry rather than rejecting it.

WKN vs. ISIN — know which you have

If you receive a 12-character code starting with DE, it is a German ISIN — use /v0/isin instead. A 6-character code is a WKN; use /v0/wkn. You can extract the WKN from a German ISIN by taking characters 5–10 and stripping leading zeros.

Multiple listings per WKN

OpenFIGI may return a result for the primary listing on XETRA (exchange code GY). The same security may also trade on Frankfurt Stock Exchange, regional German exchanges, or as a depositary receipt elsewhere. The API returns the first matching result; use the ISIN from the response to look up all listings via /v0/isin if you need the complete picture.


10. Summary

WhatDetail
Format6 alphanumeric characters [A-Z0-9], no check digit
Check algorithmNone — purely opaque sequence
Issuing authorityWM Datenservice, Frankfurt
CoverageGerman securities (equities, bonds, ETFs, warrants, structured products)
Enrichment sourceOpenFIGI (Bloomberg) via ID_WERTPAPIER
API endpointGET /v0/wkn?value=514000

For cross-referencing, see also:


Node.js integration notes

In a TypeScript codebase, define a branded type to prevent WKNs from being confused with other 6-character strings at compile time: type Wkn = string & { readonly __brand: 'Wkn' }. Validate at the system boundary — when the WKN enters your application from user input, an upstream API, or a file import — and carry the branded type through the rest of your pipeline.

WKN validation is particularly relevant in German banking integrations: online brokerage order entry, portfolio management dashboards, and wealth management reporting tools. If your application accepts WKNs from users, the absence of a check digit means any plausible-looking 6-character string passes format validation. Pair the API call with client-side pattern matching (/^[A-Z0-9]{6}$/i) for instant UI feedback, and confirm against OpenFIGI on submission.

Caching strategy

WKN-to-instrument mappings change infrequently — corporate actions aside, a given WKN refers to the same security for years. Cache validated results in Redis with a 24-hour TTL using the normalised WKN as the key. The IsValid API already caches OpenFIGI responses for 24 hours on its end; your own cache layer eliminates the network round trip for repeated lookups of the same identifier within a session.

  • Assert process.env.ISVALID_API_KEY at server startup, not lazily at first request
  • Use Promise.allSettled() for batch WKN validation — it collects all results without aborting on the first failure
  • Log the full parsed API response alongside the raw WKN — the ISIN and FIGI returned are useful for downstream reconciliation
  • If you need the full ISIN from a WKN, use the isin field from the response rather than constructing it manually