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 boreholeaiThe 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-dotenv2. 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_here3. 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 environmentBasic 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.pdfThe 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 hereError 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")| Exception | HTTP Status | Description |
|---|---|---|
| AuthenticationError | 401 | API key is missing, invalid, or has been revoked |
| InsufficientCreditsError | 402 | Account does not have enough credits to process the document. No credits are deducted. |
| RateLimitError | 429 | Too many requests in a short time. Wait and retry. |
| ServerError | 5xx | An internal server error occurred. Retry after a short delay. |
| JobFailedError | — | The 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 savedThe 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:
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:
- Uploads all files to the BoreholeAI API and receives a job ID.
- Polls the job status endpoint at regular intervals (starting at 2 seconds, increasing to 10 seconds with exponential backoff).
- When the job reaches
completedstatus, downloads all result files to the specified output directory. - Returns a
JobResultwith 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}")