Skip to main content

typizer — Python SDK для Typizer API

Официальный Python SDK для Typizer — сервиса, который извлекает данные из документов (счета, УПД, накладные, договоры, сканы и фото) в JSON по вашей схеме.

SDK сгенерирован из OpenAPI-описания Typizer API: одна функция на каждую операцию REST API, с теми же именами полей и кодами ошибок. Полная документация — docs.typizer.ru.

Установка

pip install typizer

Нужен Python 3.11 или новее. Зависимости — только httpx и attrs.

Ключ API

  1. Зарегистрируйтесь в кабинете my.typizer.ru.
  2. Откройте раздел «Ключи API» и создайте ключ со скоупом runs:write (для запуска прогонов) — подробнее о скоупах в «Ключах API».
  3. Ключ (tz_live_…) показывается один раз. Сохраните его, например в переменную окружения:
export TYPIZER_API_KEY="tz_live_…"

Быстрый старт

Извлечь данные из документа по разовой схеме (POST /v1/extract). wait=60 держит запрос до завершения прогона, но не дольше 60 секунд:

import os
import uuid

import httpx

from typizer import AuthenticatedClient
from typizer.api.runs import extract
from typizer.models import ExtractRequest, ExtractRequestSchema, Problem, Run

client = AuthenticatedClient(
    base_url="https://api.typizer.ru",
    token=os.environ["TYPIZER_API_KEY"],  # сам ключ, без слова Bearer
    timeout=httpx.Timeout(70.0),  # чуть больше, чем wait
)

schema = ExtractRequestSchema.from_dict(
    {
        "type": "object",
        "properties": {
            "invoice_number": {"type": "string"},
            "total": {"type": "number"},
            "inn": {"type": "string", "x-typizer-check": "inn"},
        },
        "required": ["invoice_number", "total"],
    }
)

with client as client:
    run = extract.sync(
        client=client,
        body=ExtractRequest(schema=schema, url="https://typizer.ru/samples/invoice.pdf"),
        wait=60,
        idempotency_key=str(uuid.uuid4()),  # новый ключ на каждую операцию
    )

if isinstance(run, Problem):
    raise RuntimeError(f"{run.code}: {run.detail} ({run.doc_url})")
assert isinstance(run, Run)

print(run.status)  # succeeded | failed | queued | processing
print(run.output)  # результат в формате JSON по вашей схеме

Если прогон не успел завершиться за wait, придёт Run со статусом queued или processing — дождитесь его через typizer.api.runs.get_run или вебхук (см. ниже и «Получить результат»).

Типизатор: схема, сохранённая один раз

Схему удобно сохранить как типизатор (POST /v1/typizers) и запускать его по id:

import os
import uuid

from typizer import AuthenticatedClient
from typizer.api.runs import create_run
from typizer.api.typizers import create_typizer
from typizer.models import CreateRunRequest, CreateTypizerRequest, CreateTypizerRequestSchema, Typizer

client = AuthenticatedClient(base_url="https://api.typizer.ru", token=os.environ["TYPIZER_API_KEY"])

with client as client:
    typizer = create_typizer.sync(
        client=client,
        body=CreateTypizerRequest(
            name="Счета поставщиков",
            schema=CreateTypizerRequestSchema.from_dict(
                {
                    "type": "object",
                    "properties": {
                        "invoice_number": {"type": "string"},
                        "total": {"type": "number"},
                    },
                    "required": ["invoice_number", "total"],
                }
            ),
        ),
    )
    assert isinstance(typizer, Typizer)

    run = create_run.sync(
        typizer.id,
        client=client,
        body=CreateRunRequest(url="https://typizer.ru/samples/invoice.pdf"),
        wait=60,
        idempotency_key=str(uuid.uuid4()),
    )
    print(run)

Файл с диска передаётся через multipart: CreateRunFilesBody(file=File(payload=f, file_name="invoice.pdf")) (File — из typizer.types), для extract — ExtractFilesBody.

Синхронные и асинхронные вызовы

Каждая операция — отдельный модуль typizer.api.<тег>.<операция> (например, typizer.api.runs.extract) с четырьмя функциями:

Функция Что возвращает
sync(...) разобранную модель (Run, Typizer, …), объект ошибки Problem или None
sync_detailed(...) Response: status_code, headers, content и parsed
asyncio(...) то же, что sync, но async
asyncio_detailed(...) то же, что sync_detailed, но async

Асинхронный вариант того же запроса:

import asyncio
import os

from typizer import AuthenticatedClient
from typizer.api.runs import get_run
from typizer.models import Run


async def main() -> None:
    client = AuthenticatedClient(base_url="https://api.typizer.ru", token=os.environ["TYPIZER_API_KEY"])
    async with client as client:
        run = await get_run.asyncio("run_…", client=client)
        if isinstance(run, Run):
            print(run.status)


asyncio.run(main())

Обработка ошибок

Любая ошибка API приходит в формате application/problem+json (RFC 9457). SDK не бросает исключение на документированный код ошибки — sync/asyncio возвращают объект Problem:

  • code — машиночитаемый код (ProblemCode: invalid_request, unauthorized, insufficient_balance, rate_limited, …);
  • detail — описание конкретного случая, param — поле запроса, если виновато оно;
  • doc_url — страница этого кода: https://docs.typizer.ru/errors/<code>/;
  • request_id — приложите его к обращению в поддержку (support@typizer.ru).
import os
import uuid

from typizer import AuthenticatedClient
from typizer.api.runs import create_run
from typizer.models import CreateRunRequest, Problem, ProblemCode

client = AuthenticatedClient(base_url="https://api.typizer.ru", token=os.environ["TYPIZER_API_KEY"])

response = create_run.sync_detailed(
    "tz_…",
    client=client,
    body=CreateRunRequest(url="https://typizer.ru/samples/invoice.pdf"),
    idempotency_key=str(uuid.uuid4()),
)
problem = response.parsed
if isinstance(problem, Problem):
    if problem.code == ProblemCode.RATE_LIMITED:
        print("повторить через", response.headers.get("Retry-After"), "с")
    elif problem.code == ProblemCode.INSUFFICIENT_BALANCE:
        print("пополните баланс в кабинете")
    else:
        print(problem.code, problem.detail, problem.doc_url, problem.request_id)

Повторять имеет смысл rate_limited (после Retry-After), upstream_unavailable и internal_error; при сетевой ошибке повторяйте запрос с тем же Idempotency-Key — второй раз ничего не создастся и не спишется. Остальные коды не исчезнут от повтора: сначала исправьте причину. Все коды со статусами HTTP — «Коды ошибок», правила повторов — «Обработка ошибок и повторов».

Кроме Problem, возможны исключения транспортного уровня: httpx.TimeoutException (истёк timeout клиента) и typizer.errors.UnexpectedStatus — только если клиент создан с raise_on_unexpected_status=True и сервер вернул код, которого нет в описании API.

Вебхуки

Вместо ожидания результат можно получать вебхуком: укажите webhook_url в запросе на прогон или создайте конечную точку через typizer.api.webhooks.create_webhook_endpoint:

import os

from typizer import AuthenticatedClient
from typizer.api.webhooks import create_webhook_endpoint, test_webhook_endpoint
from typizer.models import CreateWebhookEndpointRequest, WebhookEndpoint, WebhookEventType

client = AuthenticatedClient(base_url="https://api.typizer.ru", token=os.environ["TYPIZER_API_KEY"])

endpoint = create_webhook_endpoint.sync(
    client=client,
    body=CreateWebhookEndpointRequest(
        url="https://your-server.example/typizer/webhook",
        events=[WebhookEventType.RUN_SUCCEEDED, WebhookEventType.RUN_FAILED],
    ),
)
assert isinstance(endpoint, WebhookEndpoint)
print(endpoint.secret)  # whsec_… — ключ для проверки подписи, храните как секрет

test_webhook_endpoint.sync(endpoint.id, client=client)  # пришлёт тестовый run.succeeded

Вебхуки подписываются по спецификации Standard Webhooks (HMAC-SHA256). Функции проверки подписи в SDK нет: готовая реализация на hmac/hashlib без сторонних пакетов и тестовый вектор — в «Приёме вебхуков». Никогда не обрабатывайте тело вебхука, не проверив подпись.

Документация

Вопросы и проблемы — support@typizer.ru.

Лицензия

MIT — см. файл LICENSE.

Metadata

Release files for typizer 0.1.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for typizer 0.1.0
File Size Uploaded Provenance Actions
typizer-0.1.0.tar.gz 96.8 kB Without provenance Details for typizer-0.1.0.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for typizer 0.1.0
File Interpreter ABI Platform Actions
typizer-0.1.0-py3-none-any.whl Python 3 none any Details for typizer-0.1.0-py3-none-any.whl

Total release size: 393.9 kB

Release files / typizer-0.1.0.tar.gz

Download URL typizer-0.1.0.tar.gz
Size 96.8 kB
Tags Source
SHA-256 checksum
How to use checksums
cdb009decd6297f1fe75872fb8d269dab1cc024b4422754419a4800f2165b061
BLAKE2b-256 checksum
How to use checksums
daa7d325c41fcfc1c95343c64732b41108ea7616380c80c2fe28575f5ec661fd
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.11.15 {"installer":{"name":"uv","version":"0.11.15","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

Release files / typizer-0.1.0-py3-none-any.whl

Download URL typizer-0.1.0-py3-none-any.whl
Size 297.2 kB
Tags Python 3
SHA-256 checksum
How to use checksums
e7402dfa3fddfac98b772d2536687c927334a568a59e9bed96e3b1c04ffcb1a4
BLAKE2b-256 checksum
How to use checksums
4b34f277c5ee6ffad83198209aff60cc9b0af3e6a5de45b9f9acdd71eef2c496
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.11.15 {"installer":{"name":"uv","version":"0.11.15","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

Security for typizer 0.1.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Release history Release notifications | RSS feed

This release

0.1.0 This release

2 release files No provenance

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page