Skip to main content

The Drive AI SDKs

Python and TypeScript clients for The Drive AI developer API — a set of file intelligence endpoints for extracting structured data, analyzing documents, making grounded decisions, converting to markdown, and generating thumbnails from any file or URL. Built for AI agents and developers who need to process documents programmatically.

This is not the SDK for The Drive AI's core product. These are standalone developer APIs available at dev.thedrive.ai.

Website | API Docs | Get API Key

Installation

Python

pip install thedriveai

TypeScript

npm install @thedriveai/sdk

Quick start

Python

from thedriveai import TheDriveAI

client = TheDriveAI(api_key="tda_live_...")

result = client.extract(
    file=open("invoice.pdf", "rb"),
    schema={
        "vendor": {"type": "string", "description": "Company name"},
        "total": {"type": "number", "description": "Total amount due"},
    },
)
print(result.data["vendor"])  # "Acme Corp"
print(result.data["total"])   # 1234.56

TypeScript

import { TheDriveAI } from "@thedriveai/sdk";
import { readFileSync } from "fs";

const client = new TheDriveAI({ apiKey: "tda_live_..." });

const result = await client.extract({
  file: readFileSync("invoice.pdf"),
  schema: {
    vendor: { type: "string", description: "Company name" },
    total: { type: "number", description: "Total amount due" },
  },
});
console.log(result.data.vendor); // "Acme Corp"

Extract

Pull structured data from any file or URL. Define the fields you want, get typed results back.

result = client.extract(
    url="https://example.com/receipt.pdf",
    schema={
        "merchant": {"type": "string", "description": "Store name"},
        "date": {"type": "string", "description": "Purchase date"},
        "items": {
            "type": "array",
            "description": "Line items",
            "items": {
                "type": "object",
                "properties": {
                    "name": {"type": "string"},
                    "price": {"type": "number"},
                },
            },
        },
        "total": {"type": "number", "description": "Total amount", "required": True},
    },
    model="accurate",
)

print(result.data)
print(result.confidence)       # {"merchant": "high", "date": "high", ...}
print(result.field_status)     # per-field found/not_found status
print(result.credits_used)

Using Pydantic models (Python)

from pydantic import BaseModel, Field

class Invoice(BaseModel):
    vendor: str = Field(description="Company name")
    total: float = Field(description="Total amount due")
    is_paid: bool = Field(description="Whether the invoice is paid")

result = client.extract(file="invoice.pdf", schema=Invoice)

Using Zod schemas (TypeScript)

import { fromZod } from "@thedriveai/sdk";
import { z } from "zod";

const Invoice = z.object({
  vendor: z.string().describe("Company name"),
  total: z.number().describe("Total amount due"),
  is_paid: z.boolean().describe("Whether the invoice is paid"),
});

const result = await client.extract({
  file: readFileSync("invoice.pdf"),
  schema: fromZod(Invoice),
});

Analyze

Compute, reason, and derive answers from documents. Unlike extract (which finds existing data), analyze can perform calculations and make inferences.

result = client.analyze(
    file="financial_report.pdf",
    schema={
        "total_revenue": {"type": "number", "description": "Sum of all revenue line items"},
        "is_profitable": {"type": "boolean", "description": "Whether net income is positive"},
        "risk_factors": {"type": "array", "items": {"type": "string"}, "description": "Key risks mentioned"},
    },
    include_steps=True,  # see the agent's reasoning trace
)

for name in result.data:
    print(f"{name}: {result.data[name]}")
    print(f"  reasoning: {result.reasoning[name]}")
    print(f"  confidence: {result.confidence[name]}")
const result = await client.analyze({
  file: readFileSync("financial_report.pdf"),
  schema: {
    total_revenue: { type: "number", description: "Sum of all revenue line items" },
    is_profitable: { type: "boolean", description: "Whether net income is positive" },
  },
  includeSteps: true,
});

console.log(result.data.total_revenue);        // 45200000
console.log(result.reasoning.total_revenue);   // "Summed line items from pages 3-5..."
console.log(result.confidence.total_revenue);  // 0.97

Decide

Make one coherent decision about a document, guided by your instructions and context. Unlike analyze (which researches each schema field independently), decide answers the whole schema in a single reasoning pass — use it when the fields are facets of one judgment: where to file a document, which branch a workflow should take, what to rename a file.

result = client.decide(
    file="invoice_march.pdf",
    instructions="Choose the best folder for this document and a clear filename.",
    context=[
        {"label": "folders", "content": "/Finance/2025\n/Legal/Contracts\n/HR"},
        {"label": "naming convention", "content": "type-year-month-vendor.pdf"},
    ],
    schema={
        "folder": {"type": "string", "description": "Destination folder path"},
        "rename_to": {"type": "string", "description": "Filename following the convention"},
    },
)

print(result.data["folder"])      # "/Finance/2025"
print(result.data["rename_to"])   # "invoice-2025-03-acme.pdf"
print(result.reasoning)           # one rationale for the whole decision
print(result.confidence)          # {"folder": 0.95, "rename_to": 0.9}
const result = await client.decide({
  file: readFileSync("invoice_march.pdf"),
  instructions: "Choose the best folder for this document and a clear filename.",
  context: [
    { label: "folders", content: "/Finance/2025\n/Legal/Contracts\n/HR" },
    { label: "naming convention", content: "type-year-month-vendor.pdf" },
  ],
  schema: {
    folder: { type: "string", description: "Destination folder path" },
    rename_to: { type: "string", description: "Filename following the convention" },
  },
});

console.log(result.data.folder);  // "/Finance/2025"
console.log(result.reasoning);    // one rationale for the whole decision

The document is optional — pass only context for pure-context decisions. Provider failures surface as real errors (503 retryable, 502 not), never as null answers.

Cross-document analysis

Validate and reason across multiple documents simultaneously — e.g. check an invoice against a contract.

result = client.analyze_cross(
    files=["invoice.pdf", "contract.pdf"],
    document_labels=["invoice", "contract"],
    schema={
        "rates_match": {"type": "boolean", "description": "Do invoice rates match the contract?"},
        "total_within_budget": {"type": "boolean", "description": "Is the invoice total within the contract budget?"},
    },
    include_steps=True,
)

for name in result.data:
    print(f"{name}: {result.data[name]}")
    print(f"  sources: {result.sources[name]}")  # ["[invoice] ...", "[contract] ..."]

for doc in result.documents:
    print(f"  {doc.label}: {doc.total_pages} pages")
const result = await client.analyzeCross({
  files: [readFileSync("invoice.pdf"), readFileSync("contract.pdf")],
  documentLabels: ["invoice", "contract"],
  schema: {
    rates_match: { type: "boolean", description: "Do invoice rates match the contract?" },
    total_within_budget: { type: "boolean", description: "Is the invoice total within the contract budget?" },
  },
  includeSteps: true,
});

console.log(result.data.rates_match);        // false
console.log(result.sources.rates_match);     // ['[invoice] "Rate: $175/hr"', '[contract] "Rate: $150/hr"']
console.log(result.documents[0].label);      // "invoice"

Markdown

Convert any file or URL to clean markdown.

# From a file
result = client.markdown(file="document.docx")
print(result.markdown)

# From a URL (shorthand)
md = client.markdown_url("https://example.com/about")
print(md)
const result = await client.markdown({ url: "https://example.com/about" });
console.log(result.markdown);

Thumbnails

Generate thumbnail images from files or URLs.

result = client.thumbnail(
    url="https://example.com/report.pdf",
    width=800,
    height=600,
    quality=90,
    response_type="url",  # or "base64"
)
print(result.thumbnail_url)
print(result.metadata.file_type)  # "pdf"

Screenshots

Capture a screenshot of any URL. Returns raw JPEG bytes.

jpeg_bytes = client.screenshot("https://stripe.com", width=1280, height=800)
with open("screenshot.jpg", "wb") as f:
    f.write(jpeg_bytes)
const buffer = await client.screenshot("https://stripe.com", {
  width: 1280,
  height: 800,
});

Async and batch processing

For large files or high-volume workloads, use async mode or batch processing.

Async (single file)

Submit a task and poll for results, or provide a webhook URL to get notified.

# Submit
task = client.extract_async(
    file="large-document.pdf",
    schema={
        "title": {"type": "string", "description": "Document title"},
        "author": {"type": "string", "description": "Author name"},
    },
)
print(task.task_id)    # "task_abc123"
print(task.poll_url)   # "/api/v1/jobs/task_abc123"

# Wait for completion
result = client.wait_for_task(task.task_id, poll_interval=2.0, timeout=300.0)
print(result.result)   # the extraction data

# Or use a webhook instead of polling
task = client.extract_async(
    file="large-document.pdf",
    schema={"title": {"type": "string", "description": "Document title"}},
    webhook_url="https://your-app.com/webhooks/driveai",
)

Batch (multiple files)

Process up to 20 files/URLs with a single schema.

batch = client.extract_batch(
    files=["invoice1.pdf", "invoice2.pdf", "invoice3.pdf"],
    urls=["https://example.com/invoice4.pdf"],
    schema={
        "vendor": {"type": "string", "description": "Company name"},
        "total": {"type": "number", "description": "Total amount"},
    },
)
print(batch.batch_id)  # "batch_xyz789"
print(batch.total)     # 4

# Wait for all to complete
result = client.wait_for_batch(batch.batch_id)
print(result.completed)     # 4
print(result.failed)        # 0
print(result.credits_used)  # 4
for task in result.results:
    print(task["result"]["data"])
const batch = await client.extractBatch({
  files: [readFileSync("invoice1.pdf"), readFileSync("invoice2.pdf")],
  urls: ["https://example.com/invoice3.pdf"],
  schema: {
    vendor: { type: "string", description: "Company name" },
    total: { type: "number", description: "Total amount" },
  },
});

const result = await client.waitForBatch(batch.batch_id);

Error handling

from thedriveai import TheDriveAI, TheDriveAIError

client = TheDriveAI(api_key="tda_live_...")

try:
    result = client.extract(file="doc.pdf", schema={"title": {"type": "string", "description": "Document title"}})
except TheDriveAIError as e:
    print(e.status_code)  # 400, 413, 503, etc.
    print(e.detail)       # error detail from the API
import { TheDriveAI, TheDriveAIError } from "@thedriveai/sdk";

try {
  const result = await client.extract({ ... });
} catch (e) {
  if (e instanceof TheDriveAIError) {
    console.log(e.statusCode);
    console.log(e.detail);
  }
}

Configuration

client = TheDriveAI(
    api_key="tda_live_...",
    base_url="https://dev.thedrive.ai",  # default
    timeout=120.0,                        # seconds, default
)

# Use as context manager to auto-close
with TheDriveAI(api_key="tda_live_...") as client:
    result = client.extract(...)
const client = new TheDriveAI({
  apiKey: "tda_live_...",
  baseUrl: "https://dev.thedrive.ai",  // default
  timeout: 120_000,                     // ms, default
});

API reference

Method Description Returns
extract() Extract structured data from a file or URL ExtractionResult
extract_async() Submit extraction for async processing TaskStatus
extract_batch() Batch extract from multiple files/URLs BatchStatus
analyze() Analyze a document (compute, reason, derive) AnalysisResult
analyze_async() Submit analysis for async processing TaskStatus
analyze_batch() Batch analyze multiple files/URLs BatchStatus
analyze_cross() Cross-reference and validate across 2-5 documents CrossAnalysisResult
decide() Make one coherent decision from a document and context DecisionResult
decide_async() Submit a decision for async processing TaskStatus
markdown() Convert a file or URL to markdown MarkdownResult
markdown_url() Convert URL to markdown (shorthand) str
thumbnail() Generate a thumbnail from file or URL ThumbnailResult
screenshot() Screenshot a URL bytes / ArrayBuffer
poll_task() Check async task status TaskStatus
poll_batch() Check batch status BatchStatus
wait_for_task() Poll until task completes TaskStatus
wait_for_batch() Poll until batch completes BatchStatus

Metadata

Release files for thedriveai 1.5.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 thedriveai 1.5.0
File Size Uploaded Provenance
thedriveai-1.5.0.tar.gz 12.2 kB Without provenance Details

Built distribution (wheel)

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

Total release size: 26.4 kB

Release files / thedriveai-1.5.0.tar.gz

Download URL thedriveai-1.5.0.tar.gz
Size 12.2 kB
Tags Source
SHA-256 checksum
How to use checksums
f119b897d61861515f7a698a96169c0f153c93ff14547e21816dc3c928b9a8af
BLAKE2b-256 checksum
How to use checksums
0191cfd30dfe96880842846669f419dfe72f4794924329d4d5a04e30425b878b
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.10.12 {"installer":{"name":"uv","version":"0.10.12","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 / thedriveai-1.5.0-py3-none-any.whl

Download URL thedriveai-1.5.0-py3-none-any.whl
Size 14.2 kB
Tags Python 3
SHA-256 checksum
How to use checksums
a9fed6100fd0493177355cd7751003a30848313531f1927f79facb3474b065d9
BLAKE2b-256 checksum
How to use checksums
4ff6991b22612e7117e2a92c845ffc00adbc27cb30f2df3d562e2ee8c1c3db79
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.10.12 {"installer":{"name":"uv","version":"0.10.12","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 thedriveai 1.5.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.

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