---
title: "Cyrillic transliteration to Latin (ISO 9:1995, BGN/PCGN Russian)"
method: GET
path: "/v1/text/transliterate"
tags: ["deterministic", "no-api-key", "text", "unicode", "transliteration"]
---

# Cyrillic transliteration to Latin (ISO 9:1995, BGN/PCGN Russian)

`GET /v1/text/transliterate`

## Request

- Base URL: `https://api.duoleads.com`
- URL: `https://api.duoleads.com/v1/text/transliterate`
- Auth: none declared

Cyrillic transliteration to Latin using a named standard: ISO 9:1995 (one-to-one, with diacritics, covering the full standard: Russian, other Slavic, historic and non-Slavic Cyrillic letters) or BGN/PCGN, which is the Russian system only (Ukrainian, Serbian and other letters are passed through unmapped). Returns the transliteration, the source script, the standard, the mapped fraction and the unmapped characters. Other scripts are rejected with UNSUPPORTED_VALUE.

**Output (`data`):** result, source_script (Unicode script name; Latin when the text has no Cyrillic, which is returned unchanged), standard (string: the validated standard, iso-9 by default; on text with no Cyrillic it is echoed although no character needed converting), coverage (0-1 fraction of non-ASCII characters mapped), unmapped (characters passed through). iso-9 maps every letter of ISO 9:1995 (Russian, Ukrainian, Belarusian, Serbian, Macedonian, Bulgarian, historic and non-Slavic Cyrillic, e.g. і -> ì, ѣ -> ě, ә -> a̋, қ -> k̦); a base letter plus combining marks is one unit. bgn-pcgn is the Russian system only: other Cyrillic letters are returned unmapped and lower coverage.

Deterministic: identical input returns identical output, so the response is served with `Cache-Control: private, max-age=31536000, immutable` (the paying client may cache it indefinitely; shared caches must not, because the response is paid).

Sources: romanisation-tables ISO 9:1995 (full Cyrillic repertoire) and BGN/PCGN Russian system (published 2026-09-29, character correspondences (facts); see sources/translit.md). Echoed in `meta.sources`.

Price: $0.05 USDC per call (x402, Base). Route contract version 1.0.0. Docs: https://api.duoleads.com/docs#text-transliterate

## Query parameters

- `text` string, required
- `from` string
- `standard` string
- `case` 'preserve' | 'lower' | 'upper'

## Response `200`

Paid and settled. `data` is route-specific; a route that judges its input returns 200 with `data.valid: false` for a bad value.

- object
  - `ok` unknown, required
  - `route` '/v1/text/transliterate', required
  - `version` '1.0.0', required
  - `data` object, required: result, source_script (Unicode script name; Latin when the text has no Cyrillic, which is returned unchanged), standard (string: the validated standard, iso-9 by default; on text with no Cyrillic it is echoed although no character needed converting), coverage (0-1 fraction of non-ASCII characters mapped), unmapped (characters passed through). iso-9 maps every letter of ISO 9:1995 (Russian, Ukrainian, Belarusian, Serbian, Macedonian, Bulgarian, historic and non-Slavic Cyrillic, e.g. і -> ì, ѣ -> ě, ә -> a̋, қ -> k̦); a base letter plus combining marks is one unit. bgn-pcgn is the Russian system only: other Cyrillic letters are returned unmapped and lower coverage.
    - `result` string, required
    - `source_script` string, required
    - `standard` string, required
    - `coverage` number, required
    - `unmapped` string, required
  - `meta` Meta, required
    - `disclaimer` string, required: Legal short disclaimer, identical on every response.
    - `request_id` string, required: ULID.
    - `computed_at` string, date-time, required: RFC 3339 UTC with milliseconds.
    - `price_usd` string, required: Decimal string, "0.05".
    - `deterministic` boolean, required
    - `sources` object[]: Present only on routes that read a vendored dataset: the exact edition that answered.
      - `id` string, required
      - `version` string, required
      - `published` string, required
      - `attribution` string
      - `licence` string

## Other responses

- `400`: MISSING_PARAM, INVALID_PARAM or UNSUPPORTED_VALUE. Not charged: validation runs before the paywall.
- `402`: Payment required. No valid PAYMENT-SIGNATURE was supplied: read the base64 PAYMENT-REQUIRED header (or this body) for the price ($0.05 = 50000 atomic USDC on eip155:8453), sign an EIP-3009 authorization and retry. Also returned when settlement is declined (PAYMENT_FAILED). Nothing is charged on a 402.
- `404`: NOT_FOUND: unknown path. Not charged.
- `405`: METHOD_NOT_ALLOWED: only GET and HEAD are served. Not charged.
- `413`: INPUT_TOO_LARGE: a parameter exceeded its documented maximum length. Not charged.
- `500`: INTERNAL: a server bug. Not charged.

---

[API](https://skmtc.dev/duoleads/apis/duo-data-utilities-iban-isin-vat-tax-id-barcode-timezone-geo.md) · [All operations](https://skmtc.dev/duoleads/apis/duo-data-utilities-iban-isin-vat-tax-id-barcode-timezone-geo/llms.txt) · [OpenAPI document](https://skmtc.dev/duoleads/apis/duo-data-utilities-iban-isin-vat-tax-id-barcode-timezone-geo/revisions/18790d59615e?raw)
