Metadata-Version: 2.5
Name: docu-devs-api-client
Version: 1.12.1
Summary: A client library for accessing DocuDevs API
Project-URL: Homepage, https://www.docudevs.ai/
Project-URL: Repository, https://github.com/piizei/docudevs.git
Project-URL: Documentation, https://docs.docudevs.ai
Author: pj@docudevs.ai
Keywords: ai document processing,docudevs client,document processing,document to data,ocr
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Requires-Python: <4.0,>=3.9
Requires-Dist: asyncio>=3.4.3
Requires-Dist: attrs>=21.3.0
Requires-Dist: click>=8.0.0
Requires-Dist: httpx<1.0.0,>=0.28.1
Requires-Dist: pydantic>=2.0.0
Requires-Dist: python-dateutil>=2.8.0
Provides-Extra: dev
Requires-Dist: mypy>=1.15.0; extra == 'dev'
Requires-Dist: openapi-python-client<0.27,>=0.24.2; extra == 'dev'
Requires-Dist: pytest-asyncio>=0.26.0; extra == 'dev'
Requires-Dist: pytest-cov>=7.1.0; extra == 'dev'
Requires-Dist: pytest>=8.3.5; extra == 'dev'
Requires-Dist: ruff>=0.11.2; extra == 'dev'
Description-Content-Type: text/markdown

# Docudevs api client

This is a client-library for docudevs API, the most accurate document to data service.
Documentation available at [docs.docudevs.ai](https://docs.docudevs.ai/)

Contract-analysis runs may capture a package of up to 32 explicitly selected documents (including the anchor) and 32 MiB of source material. `create_contract_analysis_run` accepts `package_members`, `expected_missing_documents`, and `excluded_documents`; the CLI `knowledge-base contract-analysis run-create` accepts matching JSON-array files. Package member order does not establish precedence.

Finding reviews use a separate append-only record and never replace the machine assessment. Use `get_contract_analysis_run_reviews(run_id)` to read current dispositions and `put_contract_analysis_run_review(...)` with the result fingerprint, expected review revision, disposition, and idempotency key to record one. The CLI exposes the same operations as `run-reviews` and `review`; the latter accepts evidence references from a JSON file.

Use `propose_contract_analysis_finding_test_case(...)` to turn one captured finding into an unapproved expectation in a new suite revision. Supply the exact run/result/criterion/target identities, the reviewer-selected expected assessment, rationale, current suite revision, and an idempotency key. The captured package is copied into the proposal. Approve it explicitly, run a new scored trial, attest the report, and publish separately; proposal creation does not trigger any of those actions. The CLI equivalent is `knowledge-base contract-analysis propose-test-case`. If multiple suite cases share the same anchor, pass `suite_case_id` to `create_contract_analysis_trial(...)` (CLI: `trial --suite-case-id`) to select the exact approved case.

## Installation

```bash
pip install docu-devs-api-client
```

## Case records

Create a records case, load rows, and classify them against a category tree. Long-running calls return a job handle; the `*_and_wait` variants block until the job finishes.

```python
import os

from docudevs import DocuDevsClient

api = DocuDevsClient(token=os.environ["DOCUDEVS_API_KEY"])
case = await api.create_records_case(
    "Product classification",
    key="ean",
    text=["name", "generic_name", "ingredients"],
    label="leaf",
    metadata=["brand"],
    target_depth=[1, 2, 3],
)
await case.import_records_and_wait(rows)  # dicts keyed by the field names above
await case.set_tree_and_wait(nodes, name="Taxonomy v1")

job = await case.classify_and_wait(keys=["4001", "4002"], llm_level="MINI")
for row in await job.flagged():
    await row.accept()  # or row.correct("4.1.2", reason="...") / row.feedback("...")

await case.memo.add("Oat drinks belong under 4.1", scope="4.1")
evaluation = await case.holdout_eval_and_wait({"baseline": {}, "no memo": {"memo": "none"}})
print(evaluation.report.summary())
```

`api.records_case(case_id)` returns the same handle for an existing case without making a request; the first classify call with plain rows reads the dataset's field mapping from the server. `case.get_record(key)` reads one record back, and `case.pending_actions()` returns `AgentAction` objects with `confirm()` and `reject()`. `classify_scores(results, truth, tree=nodes)` scores classify results per tree level against a `{key: code}` mapping as `LevelScore` counts (`1/2 (50%)`); `classify_accuracy` returns the same as fractions.

## Workbook normalization (v1)

Submit one native `.xlsx` workbook with a nonblank interpretation prompt. Do not provide a target schema. Poll the job, then inspect the returned dataset envelope and its `issues` (a dataset may be `complete` or `needsReview`). Fetch the caller-inspectable transformation plan and source map when you need provenance. The SDK does not start downstream processing automatically; choose the next step in your application.

```python
guid = await client.submit_and_process_document(
    workbook,
    "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
    prompt="Normalize the discovered tables and preserve source references.",
    extraction_mode="WORKBOOK",
)
dataset = await client.wait_until_ready(guid, result_format="json")
if dataset.get("status") == "needsReview":
    print(dataset.get("issues", []))
plan = await client.get_workbook_plan(guid)
source_map = await client.get_workbook_source_map(guid)
summary = await client.get_workbook_summary(guid)
# Caller-controlled next step.
```

Workbook normalization v1 accepts exactly one workbook per job. Cross-workbook joins are a required future capability and are not silently enabled by this SDK.
