Convert Documents

Extract structured data from documents using AI-powered OCR

Convert Documents

The Convert operation extracts structured data from documents using AI-powered OCR. You provide a document (image or PDF) and a document type code, and DocuTray returns the extracted fields as JSON according to the document type's schema.

Quick Start

from pathlib import Path
from docutray import Client

client = Client(api_key="YOUR_API_KEY")

result = client.convert.run(
    file=Path("invoice.pdf"),
    document_type_code="invoice"
)

print(result.data)
import DocuTray from 'docutray';
import { readFileSync } from 'fs';

const client = new DocuTray({ apiKey: 'YOUR_API_KEY' });

const result = await client.convert.run({
  file: readFileSync('invoice.pdf'),
  filename: 'invoice.pdf',
  documentTypeCode: 'invoice',
});

console.log(result.data);
curl -X POST https://app.docutray.com/api/convert \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -F "image=@invoice.pdf" \
  -F "document_type_code=invoice"

Response

# result is a ConversionResult
print(result.data)
# {
#     "invoice_number": "F-2024-001",
#     "issue_date": "2024-01-15",
#     "vendor_name": "Acme Corporation",
#     "subtotal": 1000,
#     "tax": 160,
#     "total": 1160
# }
// result is a ConversionResult
console.log(result.data);
// {
//   invoice_number: 'F-2024-001',
//   issue_date: '2024-01-15',
//   vendor_name: 'Acme Corporation',
//   subtotal: 1000,
//   tax: 160,
//   total: 1160
// }
{
  "data": {
    "invoice_number": "F-2024-001",
    "issue_date": "2024-01-15",
    "vendor_name": "Acme Corporation",
    "subtotal": 1000,
    "tax": 160,
    "total": 1160
  }
}

Async Conversion

For large documents or batch processing, use async conversion. The document is processed in the background and you can poll for the result.

# Start async conversion
status = client.convert.run_async(
    file=Path("large_document.pdf"),
    document_type_code="invoice"
)

print(f"Conversion ID: {status.conversion_id}")
print(f"Status: {status.status}")  # ENQUEUED

# Wait for completion (polls automatically)
result = status.wait()

if result.is_success():
    print(result.data)
elif result.is_error():
    print(f"Error: {result.error}")
// Start async conversion
const status = await client.convert.runAsync({
  file: readFileSync('large_document.pdf'),
  filename: 'large_document.pdf',
  documentTypeCode: 'invoice',
});

console.log(`Conversion ID: ${status.conversion_id}`);
console.log(`Status: ${status.status}`); // ENQUEUED

// Wait for completion (polls automatically)
const result = await status.wait({
  onStatus: (s) => console.log(`Status: ${s.status}`),
});

if (result.isSuccess()) {
  console.log(result.data);
} else if (result.isFailed()) {
  console.log(`Error: ${result.error}`);
}
# Start async conversion
curl -X POST https://app.docutray.com/api/convert-async \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -F "image=@large_document.pdf" \
  -F "document_type_code=invoice"

# Response:
# {
#   "conversion_id": "cm5vm9hx30001m5cgh0p9v8qa",
#   "status": "ENQUEUED",
#   "status_url": "https://app.docutray.com/api/convert-async/status/cm5vm9hx30001m5cgh0p9v8qa"
# }

# Poll for status
curl https://app.docutray.com/api/convert-async/status/cm5vm9hx30001m5cgh0p9v8qa \
  -H "Authorization: Bearer YOUR_API_KEY"

Checking Status Manually

You can also check the status of an async conversion by its ID:

status = client.convert.get_status("cm5vm9hx30001m5cgh0p9v8qa")

if status.is_success():
    print(status.data)
const status = await client.convert.getStatus('cm5vm9hx30001m5cgh0p9v8qa');

if (status.isSuccess()) {
  console.log(status.data);
}
curl https://app.docutray.com/api/convert-async/status/cm5vm9hx30001m5cgh0p9v8qa \
  -H "Authorization: Bearer YOUR_API_KEY"

Input Methods

DocuTray supports three methods for providing documents.

File Upload

Upload a file directly from disk or memory.

from pathlib import Path

# From a file path
result = client.convert.run(
    file=Path("invoice.pdf"),
    document_type_code="invoice"
)

# From bytes
with open("invoice.pdf", "rb") as f:
    result = client.convert.run(
        file=f.read(),
        document_type_code="invoice",
        content_type="application/pdf"
    )

# From a file object
with open("invoice.pdf", "rb") as f:
    result = client.convert.run(
        file=f,
        document_type_code="invoice"
    )
import { readFileSync } from 'fs';

const result = await client.convert.run({
  file: readFileSync('invoice.pdf'),
  documentTypeCode: 'invoice',
  filename: 'invoice.pdf',
});
curl -X POST https://app.docutray.com/api/convert \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -F "image=@invoice.pdf" \
  -F "document_type_code=invoice"

URL

Provide a publicly accessible URL to the document. DocuTray will download and process it.

result = client.convert.run(
    url="https://example.com/invoice.pdf",
    document_type_code="invoice"
)
const result = await client.convert.run({
  url: 'https://example.com/invoice.pdf',
  documentTypeCode: 'invoice',
});
curl -X POST https://app.docutray.com/api/convert \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "image_url": "https://example.com/invoice.pdf",
    "document_type_code": "invoice"
  }'

Base64

Send a base64-encoded document in the request body.

import base64

with open("invoice.pdf", "rb") as f:
    encoded = base64.b64encode(f.read()).decode()

result = client.convert.run(
    file_base64=encoded,
    document_type_code="invoice",
    content_type="application/pdf"
)
import { readFileSync } from 'fs';

const encoded = readFileSync('invoice.pdf').toString('base64');

const result = await client.convert.run({
  base64: encoded,
  documentTypeCode: 'invoice',
  contentType: 'application/pdf',
});
BASE64=$(base64 -i invoice.pdf)

curl -X POST https://app.docutray.com/api/convert \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d "{
    \"image_base64\": \"$BASE64\",
    \"image_content_type\": \"application/pdf\",
    \"document_type_code\": \"invoice\"
  }"

Document Metadata

You can attach custom metadata to any conversion. This metadata is returned in status responses and webhooks, useful for tracking your internal references.

result = client.convert.run(
    file=Path("invoice.pdf"),
    document_type_code="invoice",
    document_metadata={"customer_id": "cust_123", "batch": "2024-Q1"}
)
const result = await client.convert.run({
  file: readFileSync('invoice.pdf'),
  filename: 'invoice.pdf',
  documentTypeCode: 'invoice',
  documentMetadata: { customer_id: 'cust_123', batch: '2024-Q1' },
});
curl -X POST https://app.docutray.com/api/convert \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -F "image=@invoice.pdf" \
  -F "document_type_code=invoice" \
  -F 'document_metadata={"customer_id": "cust_123", "batch": "2024-Q1"}'

Parameters

ParameterTypeRequiredDescription
document_type_codestringYesCode identifying the document type schema to use
fileFileNoFile to process (path, bytes, or file object)
urlstringNoPublic URL of the document to download and process
file_base64 / base64stringNoBase64-encoded document content
content_typestringNoMIME type of the document (auto-detected if not provided)
document_metadataobjectNoCustom metadata to attach to the conversion

You must provide exactly one of file, url, or file_base64/base64.

Supported file formats: JPEG, PNG, GIF, BMP, WebP, PDF (up to 100MB)

Error Handling

from docutray import (
    AuthenticationError,
    BadRequestError,
    RateLimitError,
    NotFoundError,
    DocuTrayError,
)

try:
    result = client.convert.run(
        file=Path("invoice.pdf"),
        document_type_code="invoice"
    )
except AuthenticationError:
    print("Invalid API key")
except BadRequestError as e:
    print(f"Invalid request: {e.message}")
except RateLimitError as e:
    print(f"Rate limited. Retry after {e.retry_after}s")
except NotFoundError:
    print("Document type not found")
except DocuTrayError as e:
    print(f"Error: {e.message}")
import {
  AuthenticationError,
  BadRequestError,
  RateLimitError,
  NotFoundError,
  DocuTrayError,
} from 'docutray';

try {
  const result = await client.convert.run({
    file: readFileSync('invoice.pdf'),
    filename: 'invoice.pdf',
    documentTypeCode: 'invoice',
  });
} catch (error) {
  if (error instanceof AuthenticationError) {
    console.error('Invalid API key');
  } else if (error instanceof RateLimitError) {
    console.error(`Rate limited. Retry after ${error.retryAfter}s`);
  } else if (error instanceof NotFoundError) {
    console.error('Document type not found');
  } else if (error instanceof DocuTrayError) {
    console.error(`Error: ${error.message}`);
  }
}

Complete Code

End-to-end example that converts a document with error handling and result processing.

from pathlib import Path
from docutray import Client, AuthenticationError, RateLimitError, DocuTrayError

client = Client(api_key="YOUR_API_KEY")

try:
    # Sync conversion for small documents
    result = client.convert.run(
        file=Path("invoice.pdf"),
        document_type_code="invoice",
        document_metadata={"source": "email", "batch": "2024-Q1"}
    )

    # Access extracted data
    data = result.data
    print(f"Invoice: {data.get('invoice_number')}")
    print(f"Total: ${data.get('total')}")

except AuthenticationError:
    print("Check your API key")
except RateLimitError as e:
    print(f"Rate limited. Retry after {e.retry_after} seconds")
except DocuTrayError as e:
    print(f"Conversion failed: {e.message}")
finally:
    client.close()
import DocuTray, {
  AuthenticationError,
  RateLimitError,
  DocuTrayError,
} from 'docutray';
import { readFileSync } from 'fs';

const client = new DocuTray({ apiKey: 'YOUR_API_KEY' });

try {
  // Sync conversion for small documents
  const result = await client.convert.run({
    file: readFileSync('invoice.pdf'),
    filename: 'invoice.pdf',
    documentTypeCode: 'invoice',
    documentMetadata: { source: 'email', batch: '2024-Q1' },
  });

  // Access extracted data
  const data = result.data;
  console.log(`Invoice: ${data.invoice_number}`);
  console.log(`Total: $${data.total}`);
} catch (error) {
  if (error instanceof AuthenticationError) {
    console.error('Check your API key');
  } else if (error instanceof RateLimitError) {
    console.error(`Rate limited. Retry after ${error.retryAfter}s`);
  } else if (error instanceof DocuTrayError) {
    console.error(`Conversion failed: ${error.message}`);
  }
}

SDK Reference

For detailed class and method documentation:

On this page