docs: rewrite README to lead with the v2 API - #112
Conversation
Restructure the README around the v2 (DPT-3) surface so new users and AI agents reach the current API first: - Quickstart shows the core parse -> extract flow in one script - Dedicated Parse, Extract, and async jobs sections with response field tables, service_tier, and wait() semantics - New limits table (file types, 50 MiB, 100 pages) - v1 condensed to a single section with a method table and split example; full reference remains in api.md - Update playground and API-key links to ade.landing.ai - Lowercase v1/v2 in prose Remove the MCP Server section: landingai-ade-mcp is generated by the Stainless toolchain, which sunsets on 2026-09-01, so the server will no longer be regenerated. Removing the recommendation until its future is decided (it also only covers the v1 API today). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
Rewrites the README around the current v2 API while retaining concise v1 guidance.
Changes:
- Adds v2 parse, extract, jobs, and async examples.
- Consolidates setup, errors, environments, and advanced usage.
- Condenses v1 documentation.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| ### Extract Jobs | ||
|
|
||
| For extracting structured data from large markdown documents asynchronously: | ||
| Use `client.v2.parse` to convert a document into Markdown plus a structure tree and grounding (pixel-coordinate bounding boxes for every element). Provide exactly one of `document` (a local file) or `document_url`. |
There was a problem hiding this comment.
PR description updated: the section was intentionally removed in a simplification pass; limits remain documented at docs.landing.ai.
| ``` | ||
|
|
||
| The async client mirrors this entire surface: `AsyncLandingAIADE().v2.parse(...)`, `await client.v2.parse_jobs.wait(...)`, etc. | ||
| Extract jobs work the same way: `client.v2.extract_jobs` accepts the same arguments as `client.v2.extract`. |
There was a problem hiding this comment.
Fixed in ea4f32a: now states create takes the extract arguments plus service_tier and does not accept save_to.
| from landingai_ade import AsyncLandingAIADE, DefaultAioHttpClient | ||
|
|
||
|
|
||
| async def main() -> None: | ||
| async with AsyncLandingAIADE( | ||
| apikey=os.environ.get("VISION_AGENT_API_KEY"), # This is the default and can be omitted | ||
| http_client=DefaultAioHttpClient(), | ||
| ) as client: | ||
| response = await client.parse( | ||
| document=Path("path/to/file"), | ||
| model="dpt-2-latest", | ||
| ) | ||
| print(response.chunks) | ||
|
|
||
|
|
||
| asyncio.run(main()) | ||
| async with AsyncLandingAIADE(http_client=DefaultAioHttpClient()) as client: | ||
| ... |
There was a problem hiding this comment.
Fixed in ea4f32a: wrapped in an async function. Verified runnable against the live API with the [aiohttp] extra installed.
| response), a subclass of `landingai_ade.APIStatusError` is raised, containing `status_code` and `response` properties. | ||
| ## Handling Errors | ||
|
|
||
| All errors inherit from `landingai_ade.APIError`. |
There was a problem hiding this comment.
Fixed in ea4f32a: added a paragraph documenting that the v2 helper exceptions inherit from LandingAiadeError, not APIError.
| The above interface eagerly reads the full response body when you make the request, which may not always be what you want. | ||
|
|
||
| To stream the response body, use `.with_streaming_response` instead, which requires a context manager and only reads the response body once you call `.read()`, `.text()`, `.json()`, `.iter_bytes()`, `.iter_text()`, `.iter_lines()` or `.parse()`. In the async client, these are async methods. | ||
| Prefix any method call with `.with_raw_response.` to get the raw HTTP response: |
There was a problem hiding this comment.
Fixed in ea4f32a: scoped to v1 methods.
| The context manager is required so that the response will reliably be closed. | ||
|
|
||
| ### Making custom/undocumented requests | ||
| Use `.with_streaming_response` instead to stream the body rather than reading it eagerly; it requires a context manager and reads the body only when you call `.read()`, `.text()`, `.json()`, `.iter_bytes()`, `.iter_text()`, `.iter_lines()`, or `.parse()`. These return [`APIResponse`](https://github.com/landing-ai/ade-python/tree/main/src/landingai_ade/_response.py) (or `AsyncAPIResponse`) objects. |
There was a problem hiding this comment.
Fixed in ea4f32a: scoped to v1 methods.
- api.md: point the v2 README link at the live #environments anchor - Make the Extract example standalone (define its parse call in-block) - Wrap the aiohttp example in an async function so it is runnable - strict=False: unsupported schema fields are skipped, not "reported" - Distinguish list() returning JobList from create/get/wait returning Job - Correct extract_jobs.create argument description (adds service_tier, no save_to) - Document that v2 helper exceptions inherit from LandingAiadeError, not APIError - Scope .with_raw_response / .with_streaming_response to v1 methods Kept the <your-api-key> placeholder: angle brackets match the convention used across docs.landing.ai. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
| # Block until the job finishes (polls with backoff) | ||
| try: | ||
| done = client.v2.parse_jobs.wait(job.job_id, timeout=600, raise_on_failure=True) | ||
| print(done.result.markdown[:200]) |
There was a problem hiding this comment.
Fixed in e968965: restored the result guard with a comment explaining that a cancelled job can be terminal with no result.
| | Field | Description | | ||
| | --- | --- | | ||
| | `extraction` | The extracted values, matching your schema. | | ||
| | `extraction_metadata` | Mirrors `extraction`; each field carries the character spans in the Markdown that the value came from. | | ||
| | `metadata` | Processing details, including credits used. | |
There was a problem hiding this comment.
Fixed in e968965: added the markdown row to the V2ExtractResult table.
| ### How to tell whether `None` means `null` or missing | ||
|
|
||
| In an API response, a field may be explicitly `null`, or missing entirely; in either case, its value is `None` in this library. You can differentiate the two cases with `.model_fields_set`: | ||
| On timeout, an `APITimeoutError` is raised. Timed-out requests are retried twice by default. |
There was a problem hiding this comment.
Fixed in e968965: the Timeouts section now distinguishes client transport timeouts (APITimeoutError, retried) from the v2 server wait window (HTTP 504 -> V2SyncTimeoutError) and points to jobs.
- Guard done.result in the jobs example: a cancelled job can be terminal with no result even with raise_on_failure=True - Add the missing markdown row to the V2ExtractResult field table - Distinguish client transport timeouts (APITimeoutError) from the v2 server wait window (HTTP 504 -> V2SyncTimeoutError) Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
| ``` | ||
|
|
||
| `parse_jobs.create` and `extract_jobs.create` both return a normalized `Job` -- one shape shared by parse and extract jobs, even though their upstream envelopes differ. Use `job.raw` to reach any field not surfaced on the typed model. | ||
| The `create`, `get`, and `wait` methods return a normalized `Job` with `job_id`, `status` (`pending`, `processing`, `completed`, `failed`, or `cancelled`), `progress`, `result`, `error`, and `raw` (the unmodified API envelope, for any field not surfaced on the typed model). The `list` method returns a `JobList`, a list of `Job` items that also carries pagination metadata (`has_more`, `page`, `page_size`). |
There was a problem hiding this comment.
Fixed in c5a3491: the sentence now states has_more is on both endpoints and page/page_size are populated on extract job lists only.
| try: | ||
| client.parse() | ||
| client.v2.parse(document_url="https://example.com/file.pdf") |
There was a problem hiding this comment.
Fixed in c5a3491: the example now imports and catches V2SyncTimeoutError with a pointer to parse_jobs.
- JobList pagination: page/page_size are populated on extract job lists only; parse lists carry has_more (and org_id) - Error-handling example: catch V2SyncTimeoutError explicitly, since it bypasses the APIError hierarchy on v2 sync 504s Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Summary
Rewrites the README so both human users and AI agents reach the current v2 (DPT-3) API first. The old README documented v1 for its first ~220 lines and introduced
client.v2as an additive appendix; new readers were being routed to the old API by default.Structure changes
service_tierandwait()semanticsContent changes
landingai-ade-mcpis generated by the Stainless toolchain, which sunsets on 2026-09-01, so the server will no longer be regenerated. Removing the recommendation until its future is decided (it also only covers the v1 API today).ade.landing.ai(moved away fromva.landing.ai); intro links to the product rather than the docspasswordon v2 parse is intentionally not shown in README examples while it remains a spec placeholder pending PDF decryption (aide#272/#390); it stays documented in api.mdVerification
service_tier(notpriority), nomarkdown_ref/idempotency_keymodel/save_to,document_url, extract with Pydantic schema andextraction_metadata, jobs (create/wait/get/listwithservice_tier="standard"), async client, error handling, v1 parse+split, and.with_raw_response. Snippets were run verbatim apart from file paths (sample PDFs from the docs site).🤖 Generated with Claude Code