Python SDK Reference
Complete API reference for the Knowhere Python SDK, including all classes, methods, types, and error types.
Installation
pip install knowhere-python-sdk
Or with uv:
uv add knowhere-python-sdk
Classes
Knowhere
Synchronous client. The primary entry point for most applications.
class Knowhere:
def __init__(
self,
*,
api_key: Optional[str] = None,
base_url: Optional[str] = None,
timeout: Optional[float] = None,
upload_timeout: Optional[float] = None,
max_retries: Optional[int] = None,
default_headers: Optional[Dict[str, str]] = None,
) -> None
| Parameter | Type | Default | Description |
|---|---|---|---|
api_key | str | None | KNOWHERE_API_KEY env | API key (required) |
base_url | str | None | https://api.knowhereto.ai | API base URL |
timeout | float | None | 60.0 | HTTP request timeout (seconds) |
upload_timeout | float | None | 600.0 | File upload timeout (seconds) |
max_retries | int | None | 5 | Max retry attempts for retryable errors |
default_headers | Dict[str, str] | None | None | Extra headers to include in every request |
Properties
| Property | Type | Description |
|---|---|---|
jobs | Jobs | Access the jobs resource namespace |
Context Manager
with Knowhere(api_key="sk_...") as client:
result = client.parse(url="https://example.com/report.pdf")
AsyncKnowhere
Asynchronous client for high-throughput applications. Same interface as Knowhere, but all methods are async.
class AsyncKnowhere:
def __init__(
self,
*,
api_key: Optional[str] = None,
base_url: Optional[str] = None,
timeout: Optional[float] = None,
upload_timeout: Optional[float] = None,
max_retries: Optional[int] = None,
default_headers: Optional[Dict[str, str]] = None,
) -> None
Accepts the same parameters as Knowhere.
Properties
| Property | Type | Description |
|---|---|---|
jobs | AsyncJobs | Access the async jobs resource namespace |
Context Manager
async with AsyncKnowhere(api_key="sk_...") as client:
result = await client.parse(url="https://example.com/report.pdf")
Methods
Knowhere.parse()
Parse a document end-to-end: create job → upload file (if needed) → poll → download and parse results. Provide exactly one of url or file.
def parse(
self,
*,
url: Optional[str] = None,
file: Optional[Union[Path, BinaryIO, bytes]] = None,
file_name: Optional[str] = None,
data_id: Optional[str] = None,
parsing_params: Optional[ParsingParams] = None,
webhook: Optional[WebhookConfig] = None,
poll_interval: float = 10.0,
poll_timeout: float = 1800.0,
verify_checksum: bool = True,
on_upload_progress: Optional[UploadProgressCallback] = None,
on_poll_progress: Optional[PollProgressCallback] = None,
) -> ParseResult
| Parameter | Type | Default | Description |
|---|---|---|---|
url | str | None | None | URL to parse (mutually exclusive with file) |
file | Path | BinaryIO | bytes | None | None | Local file to upload and parse |
file_name | str | None | None | Override filename (inferred from Path if omitted) |
data_id | str | None | None | Idempotency / correlation identifier |
parsing_params | ParsingParams | None | Parsing configuration |
webhook | WebhookConfig | None | Webhook for job completion notifications |
poll_interval | float | 10.0 | Seconds between status polls |
poll_timeout | float | 1800.0 | Max seconds to wait for completion |
verify_checksum | bool | True | Verify SHA-256 checksum of the downloaded result |
on_upload_progress | Callable | None | None | Callback (bytes_sent, total_bytes) |
on_poll_progress | Callable | None | None | Callback (JobResult) on each poll |
Returns
Returns a ParseResult containing the manifest, typed chunks, full markdown, and raw ZIP.
Example
from pathlib import Path
# Parse from URL
result = client.parse(url="https://example.com/report.pdf")
# Parse a local file with advanced options
result = client.parse(
file=Path("report.pdf"),
parsing_params={"model": "advanced", "ocr_enabled": True},
poll_interval=5.0,
)
print(result.statistics.total_chunks)
print(result.full_markdown[:500])
Jobs.create()
Create a new parsing job.
def create(
self,
*,
source_type: str,
source_url: Optional[str] = None,
file_name: Optional[str] = None,
data_id: Optional[str] = None,
parsing_params: Optional[ParsingParams] = None,
webhook: Optional[WebhookConfig] = None,
) -> Job
| Parameter | Type | Default | Description |
|---|---|---|---|
source_type | str | — | "url" or "file" |
source_url | str | None | None | URL to parse (required when source_type="url") |
file_name | str | None | None | Original filename (required when source_type="file") |
data_id | str | None | None | Idempotency / correlation identifier |
parsing_params | ParsingParams | None | Parsing configuration |
webhook | WebhookConfig | None | Webhook for job completion notifications |
Returns
A Job object. When source_type="file", the object includes upload_url and upload_headers for the next step.
Jobs.upload()
Upload a file for a job created with source_type="file".
def upload(
self,
job: Union[Job, str],
file: Union[Path, BinaryIO, bytes],
*,
on_progress: Optional[UploadProgressCallback] = None,
) -> None
| Parameter | Type | Description |
|---|---|---|
job | Job | str | A Job object or a pre-signed upload URL string |
file | Path | BinaryIO | bytes | The file to upload |
on_progress | Callable | None | Optional callback (bytes_sent, total_bytes) |
Jobs.get()
Retrieve the current status and result of a job.
def get(self, job_id: str) -> JobResult
| Parameter | Type | Description |
|---|---|---|
job_id | str | The job identifier |
Returns
A JobResult with the current status, progress, error, and result details.
Jobs.wait()
Poll until the job reaches a terminal status (done or failed).
def wait(
self,
job_id: str,
*,
poll_interval: float = 10.0,
poll_timeout: float = 1800.0,
on_progress: Optional[PollProgressCallback] = None,
) -> JobResult
| Parameter | Type | Default | Description |
|---|---|---|---|
job_id | str | — | The job to poll |
poll_interval | float | 10.0 | Seconds between polls (adaptive backoff applied) |
poll_timeout | float | 1800.0 | Max seconds to wait before raising PollingTimeoutError |
on_progress | Callable | None | None | Callback (JobResult) on each poll |
Returns
A terminal JobResult. Raises JobFailedError if the job fails, or PollingTimeoutError if the timeout is exceeded.
Jobs.load()
Download and parse the result ZIP for a completed job.
def load(
self,
job_result: Union[JobResult, str],
*,
verify_checksum: bool = True,
) -> ParseResult
| Parameter | Type | Default | Description |
|---|---|---|---|
job_result | JobResult | str | — | A JobResult with result_url, or a direct URL string |
verify_checksum | bool | True | Verify the SHA-256 checksum from the manifest |
Returns
A fully populated ParseResult.
AsyncJobs
Asynchronous counterpart to Jobs. All methods have the same signatures but are async:
await client.jobs.create(...)
await client.jobs.upload(...)
await client.jobs.get(...)
await client.jobs.wait(...)
await client.jobs.load(...)
Types
Job
Response from POST /v1/jobs — represents a newly created job.
class Job(BaseModel):
job_id: str
status: str
source_type: str
data_id: Optional[str] = None
created_at: Optional[datetime] = None
upload_url: Optional[str] = None
upload_headers: Optional[Dict[str, str]] = None
expires_in: Optional[int] = None
| Field | Type | Description |
|---|---|---|
job_id | str | Unique job identifier |
status | str | Current job status (e.g., waiting-file, pending) |
source_type | str | "url" or "file" |
data_id | str | None | Caller-provided correlation identifier |
created_at | datetime | None | Job creation timestamp |
upload_url | str | None | Pre-signed upload URL (file mode only) |
upload_headers | Dict[str, str] | None | Headers to include in the upload request |
expires_in | int | None | Upload URL expiry in seconds |
JobResult
Response from GET /v1/jobs/{job_id} — full job status and result.
class JobResult(BaseModel):
job_id: str
status: str
source_type: str
data_id: Optional[str] = None
created_at: Optional[datetime] = None
progress: Optional[Union[float, JobProgress]] = None
error: Optional[JobError] = None
result: Optional[Dict[str, Any]] = None
result_url: Optional[str] = None
result_url_expires_at: Optional[datetime] = None
file_name: Optional[str] = None
file_extension: Optional[str] = None
model: Optional[str] = None
ocr_enabled: Optional[bool] = None
duration_seconds: Optional[float] = None
credits_spent: Optional[float] = None
| Field | Type | Description |
|---|---|---|
job_id | str | Unique job identifier |
status | str | waiting-file, pending, running, done, or failed |
progress | float | JobProgress | None | Parsing progress (when running) |
error | JobError | Error details (when failed) |
result_url | str | None | Pre-signed download URL for the result ZIP |
result_url_expires_at | datetime | None | When the download URL expires |
credits_spent | float | None | Credits consumed by this job |
Convenience Properties
| Property | Type | Description |
|---|---|---|
is_terminal | bool | True if status is done or failed |
is_done | bool | True if status is done |
is_failed | bool | True if status is failed |
JobError
Embedded error object returned when a job fails. Shares the same structure as HTTP error responses.
class JobError(BaseModel):
code: str
message: str
request_id: Optional[str] = None
details: Optional[Any] = None
| Field | Type | Description |
|---|---|---|
code | str | Canonical error code (e.g., INVALID_ARGUMENT) |
message | str | Human-readable error message |
request_id | str | None | Tracing identifier (equals job_id for job errors) |
details | Any | None | Additional error context (violations, retry hints) |
JobProgress
Progress info returned by the server during parsing.
class JobProgress(BaseModel):
total_pages: int = 0
processed_pages: int = 0
| Property | Type | Description |
|---|---|---|
fraction | float | Progress as a 0.0–1.0 fraction |
ParseResult
Eagerly-loaded result of a document parsing job. Contains the manifest, all chunks (with image bytes and table HTML already loaded), the full markdown, and the raw ZIP bytes.
class ParseResult:
manifest: Manifest
chunks: List[Chunk]
full_markdown: str
hierarchy: Optional[Any]
raw_zip: bytes
| Property | Type | Description |
|---|---|---|
manifest | Manifest | Metadata about the parsed document |
chunks | List[Chunk] | All chunks (text, image, table) |
full_markdown | str | Complete markdown of the document |
hierarchy | Any | None | Structural hierarchy data |
raw_zip | bytes | Raw ZIP archive for archival |
Convenience Properties
| Property | Type | Description |
|---|---|---|
text_chunks | List[TextChunk] | Only text chunks |
image_chunks | List[ImageChunk] | Only image chunks |
table_chunks | List[TableChunk] | Only table chunks |
job_id | str | None | Shortcut to manifest.job_id |
statistics | Statistics | Shortcut to manifest.statistics |
Methods
| Method | Returns | Description |
|---|---|---|
getChunk(chunk_id) | Chunk | None | Find a chunk by ID |
save(directory) | Path | Save all results to disk (full.md, images/, tables/, result.zip) |
Manifest
Top-level manifest describing the result ZIP contents.
class Manifest(BaseModel):
version: Optional[str] = None
job_id: Optional[str] = None
data_id: Optional[str] = None
source_file_name: Optional[str] = None
processing_date: Optional[str] = None
checksum: Optional[Checksum] = None
statistics: Optional[Statistics] = None
files: Optional[FileIndex] = None
Statistics
Aggregate statistics about the parsed document.
class Statistics(BaseModel):
total_chunks: Optional[int] = 0
text_chunks: Optional[int] = 0
image_chunks: Optional[int] = 0
table_chunks: Optional[int] = 0
total_pages: Optional[int] = 0
Chunk Types
TextChunk
class TextChunk(BaseChunk):
type: str = "text"
length: int = 0
tokens: Optional[int] = None
keywords: Optional[List[str]] = None
summary: Optional[str] = None
relationships: Optional[List[Union[Dict[str, Any], str]]] = None
ImageChunk
class ImageChunk(BaseChunk):
type: str = "image"
file_path: Optional[str] = None
original_name: Optional[str] = None
summary: Optional[str] = None
data: bytes # raw image bytes from ZIP
| Method | Returns | Description |
|---|---|---|
save(directory) | Path | Write image bytes to disk |
format (property) | str | None | Inferred format from file_path extension |
TableChunk
class TableChunk(BaseChunk):
type: str = "table"
file_path: Optional[str] = None
original_name: Optional[str] = None
table_type: Optional[str] = None
summary: Optional[str] = None
html: str # table HTML from ZIP
| Method | Returns | Description |
|---|---|---|
save(directory) | Path | Write table HTML to disk |
All chunks share these base fields:
class BaseChunk(BaseModel):
chunk_id: str
type: str
content: str = ""
path: Optional[str] = None
ParsingParams
Optional parsing parameters for job creation.
class ParsingParams(TypedDict, total=False):
model: str
ocr_enabled: bool
kb_dir: str
doc_type: str
smart_title_parse: bool
summary_image: bool
summary_table: bool
summary_txt: bool
add_frag_desc: bool
| Field | Type | Description |
|---|---|---|
model | str | Parsing model to use (e.g., "advanced") |
ocr_enabled | bool | Enable OCR for scanned documents |
doc_type | str | Document type hint |
smart_title_parse | bool | Enable smart title detection |
summary_image | bool | Generate image summaries |
summary_table | bool | Generate table summaries |
summary_txt | bool | Generate text chunk summaries |
add_frag_desc | bool | Add fragment descriptions |
WebhookConfig
Webhook configuration for job completion notifications.
class WebhookConfig(TypedDict, total=False):
url: str
| Field | Type | Description |
|---|---|---|
url | str | HTTPS URL to receive job completion callbacks |
Error Types
All SDK errors inherit from KnowhereError:
KnowhereError
Root exception for every error raised by the SDK.
class KnowhereError(Exception):
message: str
APIStatusError
Raised for HTTP 4xx / 5xx responses. The base class for all HTTP status errors.
class APIStatusError(KnowhereError):
status_code: int
code: str
request_id: Optional[str]
details: Optional[Any]
body: Optional[Any]
response: httpx.Response
| Property | Type | Description |
|---|---|---|
status_code | int | HTTP status code |
code | str | Server error code (e.g., INVALID_ARGUMENT) |
request_id | str | None | Request tracing identifier |
details | Any | None | Additional error context |
body | Any | None | Raw parsed response body |
response | httpx.Response | The underlying HTTP response |
RateLimitError
Raised for HTTP 429 — includes rate limit hints from the server.
class RateLimitError(APIStatusError):
retry_after: Optional[float]
limit: Optional[int]
period: Optional[str]
| Property | Type | Description |
|---|---|---|
retry_after | float | None | Seconds to wait before retrying (None for quota exceeded) |
limit | int | None | Maximum allowed requests in the rate window |
period | str | None | Rate window unit ("second", "minute", "hour", "day") |
JobFailedError
Raised when polling detects a job has reached the failed status.
class JobFailedError(KnowhereError):
job_result: JobResult
code: str
message: str
| Property | Type | Description |
|---|---|---|
job_result | JobResult | The full job result object |
code | str | Error code from the job failure |
message | str | Error message from the job failure |
PollingTimeoutError
Raised when jobs.wait() exceeds the configured timeout.
class PollingTimeoutError(KnowhereError):
job_id: str
elapsed: float
ChecksumError
Raised when the SHA-256 checksum of a downloaded result does not match.
class ChecksumError(KnowhereError):
expected: str
actual: str
Other Error Types
| Exception | HTTP | Description |
|---|---|---|
APIConnectionError | — | Cannot reach the API (DNS, TCP, TLS) |
APITimeoutError | — | Request exceeded timeout |
ValidationError | — | Invalid arguments passed to the SDK |
InvalidStateError | — | Object in unexpected state (e.g., no upload_url) |
BadRequestError | 400 | Invalid request parameters |
AuthenticationError | 401 | Invalid or missing API key |
PaymentRequiredError | 402 | Insufficient credits |
PermissionDeniedError | 403 | Access denied |
NotFoundError | 404 | Resource not found |
ConflictError | 409 | Concurrency conflict |
InternalServerError | 500 | Server internal error |
ServiceUnavailableError | 502/503 | Service temporarily down |
GatewayTimeoutError | 504 | Gateway timeout |
Automatic Retries
The SDK automatically retries requests on retryable errors with exponential backoff and jitter:
| Error | Retried? | Condition |
|---|---|---|
| Connection errors | ✅ Always | — |
| Timeouts | ✅ Always | — |
| 409 Conflict | ✅ Always | — |
| 502/503 Unavailable | ✅ Always | — |
| 504 Gateway Timeout | ✅ Always | — |
| 429 Rate Limit | ✅ Conditional | Only when retry_after is present |
| Other 4xx/5xx | ❌ Never | — |
Backoff schedule: 0.5s × 2^attempt (capped at 30s), with ±25% jitter. When the server provides a retry_after hint, it takes precedence.
# Reduce retries for faster failure
client = Knowhere(max_retries=2)
# Increase retries for more resilience
client = Knowhere(max_retries=10)