Skip to content

Index4AI Client API Reference ​

python
from index4ai import Index4AI

Index4AI is the synchronous client for index4.ai (RAG / hybrid search). It is project-scoped and validates its API key prefix locally — see Authentication below.

For async code, use AsyncIndex4AI.

Constructor ​

python
Index4AI(
    api_key: str | None = None,
    *,
    timeout: float = 600.0,
    client: httpx.Client | None = None,
)
ParameterDefaultNotes
api_keyNoneReads INDEX4AI_API_KEY if omitted. Must start with poma_proj_gr_. Account keys (poma_acc_…) are rejected locally.
timeout600.0HTTP timeout in seconds, passed through to httpx.
clientNonePre-built httpx.Client to reuse a connection pool. Bearer header is set by the SDK either way.

The API host defaults to https://api.index4.ai and can be overridden with INDEX4AI_API_BASE_URL. Requests go to API version 1 (/v1).

Raises InvalidApiKeyError when the resolved key is missing, has the account prefix, or has any other unexpected prefix.

Authentication ​

index4.ai requires a project-level key. The Bearer token is bound to one project namespace — every ingest, every search, every list goes against that namespace.

python
import os
os.environ["INDEX4AI_API_KEY"] = "poma_proj_gr_…"

from index4ai import Index4AI
client = Index4AI()

Full provisioning flow: Authentication.

Ingest methods ​

submit ​

python
submit(
    file_path: str | os.PathLike[str] | None = None,
    *,
    remote_url: str | None = None,
    base_url: str | None = None,
    completion: str | None = None,
    attributes: dict[str, Any] | None = None,
    attribute_schema: dict[str, Any] | None = None,
) -> str

Submit a document to index4.ai ingestion. Returns the job_id. Use this when you want to capture the job ID and collect later.

ParameterEffect
file_pathLocal file to upload. Pass exactly one of file_path or remote_url; otherwise ValueError.
remote_urlPublic URL the server fetches itself — nothing is uploaded.
base_urlUsed by HTML inputs to resolve relative links against a known origin.
completionCompletion webhook, "<url>|<header>:<value>|...", capped at 1024 characters.
attributesTyped attributes stored with the document, usable as attribute_filters at query time. string, int, float and bool are inferred.
attribute_schemaDeclares attribute types that cannot be inferred, such as {"published_at": {"type": "datetime"}} (datetime, encrypted_text).

Attribute names are permanent per project: call list_attributes() first and reuse an existing name.

Raises SubmitUncertainError if the connection fails mid-submit (a job may or may not exist — check list_docs() before re-submitting) and ApiError on a non-2xx response.

collect ​

python
collect(
    job_id: str,
    *,
    show_progress: bool = False,
    initial_delay: float = 2.0,
    poll_interval: float = 2.0,
    max_interval: float = 10.0,
) -> IngestResult

Poll a previously submitted job until it reaches a final state, with adaptive backoff between initial_delay and max_interval seconds. Raises JobWaitError (carrying job_id) if the wait fails while the job keeps running; call collect(err.job_id) again to resume.

Ingest does not produce a downloadable archive. Use IngestResult.doc_id to search and manage the indexed document.

IngestResult fields: job_id, status, code, doc_id, deduplicated, replaced_doc_ids, evicted_doc_ids, usage, raw. The indexing fields (doc_id, deduplicated, replaced_doc_ids, evicted_doc_ids) are None when the server reported no indexing outcome — None means "no information", never "not deduplicated". On a deduplicated ingest, doc_id is the pre-existing document's id.

ingest ​

python
ingest(
    file_path: str | os.PathLike[str] | None = None,
    *,
    remote_url: str | None = None,
    base_url: str | None = None,
    completion: str | None = None,
    attributes: dict[str, Any] | None = None,
    attribute_schema: dict[str, Any] | None = None,
    show_progress: bool = False,
    initial_delay: float = 2.0,
    poll_interval: float = 2.0,
    max_interval: float = 10.0,
) -> IngestResult

Combined submit + collect — submit a document and wait for indexing to finish in one call.

Search methods ​

python
search(
    query: str,
    *,
    doc_filter: str | None = None,
    exclude_doc_ids: list[str] | None = None,
    return_assets: bool | None = None,
    min_relevance: float | None = None,
    target_tokens: int | None = None,
    max_tokens: int | None = None,
    attribute_filters: list[dict[str, Any]] | None = None,
) -> SearchContext

Hybrid search across every document in the project namespace. Returns a SearchContext whose .context field is a prompt-ready XML + Markdown block.

ParameterEffect
doc_filterRestrict to one document by doc_id. For per-doc Q&A, prefer search_in_doc(...).
exclude_doc_idsDrop specific docs from the candidate set (e.g. recently superseded versions).
return_assetsReturn the cited documents' figures (and tables, where available) in the response assets field, keyed by doc_id. Images are base64 data URIs referenced as [IMAGE: name] in context.
min_relevanceRelevance floor, 0–1 (default 0.3). Higher = stricter; lower-relevance hits are dropped before token budgeting.
target_tokensSoft token budget — the typical answer size (default 5000). The knob to size a response. Can never exceed max_tokens (clamped down if it would).
max_tokensHard ceiling (default 15000); only matters for tight multi-document clusters. Set it below target_tokens and the soft target is clamped down to match — the hard ceiling always wins.
attribute_filtersList of filters on document attributes, each {"attr": ..., "op": ..., "value": ...}, e.g. {"attr": "source", "op": "eq", "value": "treasury"}.

query must be a non-empty string, otherwise ValueError. The client does not expose a retrieval-tier parameter.

SearchContext fields: context, assets, query, namespace, result_count, tokens_estimated, results_dropped, detected_lang, mode, search_units.

search_in_doc ​

python
search_in_doc(
    query: str,
    doc_filter: str,
    *,
    exclude_doc_ids: list[str] | None = None,
    return_assets: bool | None = None,
    min_relevance: float | None = None,
    target_tokens: int | None = None,
    max_tokens: int | None = None,
    attribute_filters: list[dict[str, Any]] | None = None,
) -> SearchContext

Search scoped to one document. doc_filter is required here. Use for in-document chatbots, per-document summarization, and section-level retrieval.

Document methods ​

list_docs ​

python
list_docs() -> list[DocInfo]

Return every document currently indexed in the project namespace, following pagination. Emits a RuntimeWarning if the server reports a degraded page (documents it could not fetch transiently were skipped). Each DocInfo carries doc_id, title, language, filename, canonical_url, pages, chunkset_count, chunk_count, image_count, table_count, ingested_at, source_job_id, bm25_state, attributes and attribute_schema.

list_attributes ​

python
list_attributes() -> AttributeList

List the project's typed attributes. AttributeList carries attributes (a list of AttributeInfo(name, type)), max_names (the cap on distinct names) and note (server guidance). A 503 is raised as ApiError with status_code == 503 — retryable, and never to be read as "no attributes".

get_doc ​

python
get_doc(doc_id: str) -> DocInfo

Look up one document by doc_id. Raises ValueError on empty input; a 404 from the server surfaces as ApiError.

delete_doc ​

python
delete_doc(doc_id: str) -> DeleteDocResponse

Remove a document from the project namespace. The response reports vectors_deleted (index rows removed) and storage_deleted (whether the stored payload was also removed) so you can verify the cleanup landed.

Lifecycle ​

close ​

python
close() -> None

Close the underlying httpx.Client. Also called automatically when used as a context manager:

python
with Index4AI() as client:
    client.ingest("doc.pdf")
# client closed on exit

Exceptions ​

All exceptions import from index4ai and derive from Index4AIError.

ExceptionRaised when
InvalidApiKeyErrorMissing / wrong-prefix API key — raised at construction, before any HTTP. Subclass of InvalidInputError.
InvalidInputErrorInvalid or missing input to an SDK method.
ApiErrorServer returned a non-2xx response. Carries status_code, response_body, and (where relevant) job_id and file_path.
InvalidResponseErrorServer response was unparseable or missing a required field (e.g. job_id from submit).
JobWaitErrorWaiting for a submitted job failed (network, unreadable status) while the job keeps running. Carries job_id; resume with collect(err.job_id).
SubmitUncertainErrorThe connection failed while a submit was in flight; a job may already exist. Carries source; check list_docs() before re-submitting.

See also ​