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
- Зарегистрируйтесь в кабинете my.typizer.ru.
- Откройте раздел «Ключи API» и создайте ключ со скоупом
runs:write(для запуска прогонов) — подробнее о скоупах в «Ключах API». - Ключ (
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 без
сторонних пакетов и тестовый вектор — в «Приёме вебхуков».
Никогда не обрабатывайте тело вебхука, не проверив подпись.
Документация
- Документация Typizer
- SDK для TypeScript и Python
- Справочник API — REST-операция за каждой функцией SDK
- Первый вызов API
Вопросы и проблемы — 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)
| 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)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| 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.