Significant upgrade: May 8, 2026. Optimised for AU/NZ English borehole logs

Python SDK

The boreholeai Python package provides a high-level client for the BoreholeAI API. Upload borehole log PDFs or images, get structured ground profiles, test data, and annotated PDFs — all from Python.

Installation

Install the package from PyPI using pip. Requires Python 3.9 or later.

bash

pip install boreholeai

The SDK has minimal dependencies: httpx for HTTP requests. No heavy ML frameworks are installed — all processing happens server-side.

Authentication

All API requests require an API key. Get yours from the API Keys settings page. Your API key starts with bhai_.

Python

from boreholeai import BoreholeAI

# Pass the API key directly
client = BoreholeAI(api_key="bhai_your_api_key_here")

Security: Never commit your API key to version control or share it publicly. Store it in an environment variable or secrets manager. You can revoke a compromised key at any time from the dashboard and create a new one.

Using Environment Variables

Instead of passing the API key directly, you can store it in an environment variable and load it automatically using python-dotenv. This keeps your key out of source code.

1. Install python-dotenv

bash

pip install python-dotenv

2. Create a .env file

Add a .env file to your project root with your API key. Make sure to add .env to your .gitignore so the key is never committed.

.env

BOREHOLEAI_API_KEY=bhai_your_api_key_here

3. Load the key in your script

Use load_dotenv() to read the .env file, then retrieve the key with os.getenv().

Python

import os
from dotenv import load_dotenv
from boreholeai import BoreholeAI

load_dotenv()

api_key = os.getenv("BOREHOLEAI_API_KEY")
client = BoreholeAI(api_key=api_key)

4. Or let the SDK read it automatically

If the BOREHOLEAI_API_KEY environment variable is set, the client picks it up without any arguments.

Python

from dotenv import load_dotenv
from boreholeai import BoreholeAI

load_dotenv()

client = BoreholeAI()  # reads BOREHOLEAI_API_KEY from environment

Basic Usage

Processing a Single File

Pass the path to a borehole log PDF or image. The SDK uploads the file, waits for processing to complete, downloads the results, and returns a JobResult object.

Python

from boreholeai import BoreholeAI

client = BoreholeAI(api_key="bhai_your_api_key_here")

result = client.process_documents("BH01.pdf", output_dir="./results")

print(f"Job ID: {result.job_id}")
print(f"Status: {result.status}")
print(f"Pages processed: {result.num_pages}")
print(f"Credits used: {result.credits_used}")

for f in result.files:
    print(f"  {f.filename} → {f.path}")

The output_dir parameter specifies where result files are saved. If not provided, results are saved to the current working directory.

Processing a Folder

Pass a directory path to process all supported files in the folder together. Results from all files are merged into consolidated output files.

Python

result = client.process_documents("./borehole_logs/", output_dir="./results")

print(f"Total pages: {result.num_pages}")
print(f"Total credits: {result.credits_used}")

# Output files:
#   results/Borehole_ground_profile.xlsx   (merged from all input files)
#   results/Borehole_test_data.xlsx        (merged from all input files)
#   results/Borehole_ags4.ags              (merged from all input files)
#   results/BH01_annotated.pdf             (one per input file)
#   results/BH02_annotated.pdf
#   results/BH03_annotated.pdf

The SDK automatically discovers all supported file types in the directory (PDF, PNG, JPEG, TIFF, WebP). Subdirectories are not scanned — only files directly in the specified directory are processed.

Context Manager

The client can be used as a context manager to ensure the underlying HTTP connection is properly closed when you are done.

Python

from boreholeai import BoreholeAI

with BoreholeAI(api_key="bhai_xxx") as client:
    result = client.process_documents("BH01.pdf")
    print(f"Pages: {result.num_pages}")
# Connection is automatically closed here

Error Handling

The SDK raises specific exceptions for different failure scenarios. All exceptions inherit from BoreholeAIError, which includes an optional status_code attribute.

Python

from boreholeai import (
    BoreholeAI,
    AuthenticationError,
    InsufficientCreditsError,
    RateLimitError,
    ServerError,
    JobFailedError,
)

client = BoreholeAI(api_key="bhai_xxx")

try:
    result = client.process_documents("borehole.pdf")
except AuthenticationError:
    print("Invalid or revoked API key")
except InsufficientCreditsError:
    print("Not enough credits — buy more at boreholeai.com")
except RateLimitError:
    print("Too many requests — wait and retry")
except JobFailedError as e:
    print(f"Processing failed: {e}")
except ServerError:
    print("Server error — try again later")
ExceptionHTTP StatusDescription
AuthenticationError401API key is missing, invalid, or has been revoked
InsufficientCreditsError402Account does not have enough credits to process the document. No credits are deducted.
RateLimitError429Too many requests in a short time. Wait and retry.
ServerError5xxAn internal server error occurred. Retry after a short delay.
JobFailedErrorThe job was accepted but processing failed. The error message from the server is included.

Response Types

The process_documents() method returns a JobResult dataclass containing the job status and a list of downloaded files.

Python

@dataclass
class JobResult:
    job_id: str              # Unique job identifier
    status: str              # "completed"
    num_pages: int           # Total pages processed
    credits_used: int        # Credits consumed (1 per page)
    files: list[FileResult]  # Downloaded result files

@dataclass
class FileResult:
    filename: str            # e.g. "Borehole_ground_profile.xlsx"
    path: Path               # Local path where file was saved

The files list contains one entry per output file. For a single-file job, you will typically receive 4 files: two Excel workbooks, one AGS4 file, and one annotated PDF. For a folder job, you will receive the same consolidated Excel and AGS files, plus one annotated PDF per input file.

Supported File Types

The following file types can be uploaded for processing:

.pdf.png.jpg / .jpeg.tif / .tiff.webp

When processing a folder, the SDK automatically discovers all files with these extensions. Other file types are ignored. Maximum file size is 200 MB per file.

Processing & Polling

The process_documents() method is synchronous and blocking. Internally, it performs the following steps:

  1. Uploads all files to the BoreholeAI API and receives a job ID.
  2. Polls the job status endpoint at regular intervals (starting at 2 seconds, increasing to 10 seconds with exponential backoff).
  3. When the job reaches completed status, downloads all result files to the specified output directory.
  4. Returns a JobResult with the job metadata and file paths.

A progress spinner is displayed in the terminal while waiting for the job to complete. Processing time depends on the number of pages — a typical single-page log takes 30–90 seconds, with multi-page logs processing each subsequent page faster due to layout reuse.

Complete Example

A complete end-to-end example that processes a folder of borehole logs and prints the results.

Python

from boreholeai import BoreholeAI, InsufficientCreditsError

client = BoreholeAI(api_key="bhai_your_api_key_here")

try:
    result = client.process_documents(
        "./site_investigation/borehole_logs/",
        output_dir="./extracted_data",
    )

    print(f"Job {result.job_id} completed")
    print(f"  Pages processed: {result.num_pages}")
    print(f"  Credits used:    {result.credits_used}")
    print(f"  Output files:")
    for f in result.files:
        print(f"    {f.filename}")
        print(f"      → {f.path}")

except InsufficientCreditsError:
    print("Not enough credits.")
    print("Purchase credits at: https://boreholeai.com/app/settings/plan")
except Exception as e:
    print(f"Error: {e}")