Every object a call returns directly also has request_id and raw_http_response, as in Read the response. Items inside a page don't carry them (reading one raises NaceError), so read the page's own; UploadedFile and JobEvent have neither. DocumentJob, UploadedFile, UploadSession, UploadSessionStatus, JobEvent and JobRequest keep any other field the document service sends as an attribute and in model_extra, such as job.progress.
| Member | Type | Description |
|---|
job_id | str | The job's id, which every jobs method takes. |
kind | str | The operation: parse, split, classify, extract or ground, or a workspace job's, such as workspace_delete, ingestion or file_delete. |
status | str | queued, running, succeeded, failed or cancelled. |
result | Any | The result, usually once status is succeeded, else None. Classify may include a partial result while still running, with reason_status (pending, complete, failed or not_requested); a result without reason_status is complete. Its shape is on each tool's page. A succeeded job's result is None again once retention drops it; job.result_state (in model_extra) is then expired or not_retained. See Jobs and results. |
error | Any | The document service's error, usually {"code", "message"}, when the job failed. |
credits | int | None | Credits the job used; final once usage_final is True. Drex charges the job's final billable usage once, at the USD price pinned when it was admitted. credits is the document service's usage count, not a multiplier for the per-page or per-target price. A failed job is never charged, including when it produced partial results. A job cancelled before completion is not charged, including delivered parts. |
timing | DocumentTiming | None | Server measurements for every document kind, present on finished newly measured jobs. None when omitted or null on historical/unmeasured jobs and fallback list items. See Job timing. |
cost | DocumentCost | None | Recorded Drex customer charge; None until settlement. |
usage_final | bool | None | Whether credits is final. |
created_at | str | None | When the job was created, ISO 8601. |
started_at | str | None | NDI execution start, ISO 8601; None before start or when omitted by a reduced response. |
finished_at | str | None | NDI terminal time, ISO 8601; None before finish or when omitted by a reduced response. |
is_terminal | bool | True for succeeded, failed and cancelled. |
error_message | str | None | error["message"], or error itself when it is a string. |
error_code | str | None | error["code"]. |
created_at, started_at and finished_at are named SDK fields. Missing or null start/finish values normalize to None; a reduced running response during settlement can omit both, and a job Drex closes as cancelled for funding omits started_at even if NDI ran it. See Job timing for presence, nullability and duration formulas.
DocumentJobList has items: tuple[DocumentJob, ...] and next_cursor: str | None, None on the last page.
Both timers use the original server request. Upload, browser network/rendering and idle time before a later client read are excluded. For Parse, first_response_ms measures the first usable server-published preview, even if your SDK call waits for the complete result and never reads previews. When the server confirms that no preview was published and total timing is available, it equals total_ms; unavailable measurements remain None. Waiting for completion does not select a delivery mode. Other document kinds use the final total for first_response_ms and leave document_finalization_ms as None; Classify's partial labels are not separately measured. See Job timing and Parse streaming.
| Member | Type | Description |
|---|
received_at | str | Original request handler's receipt time, ISO 8601; replays preserve it. |
observed_at | str | Server time of this snapshot. |
completed_at | str | None | First terminal response preparation time, preserved across reads. |
elapsed_ms | int | None | Live server estimate, or the frozen total after completion. |
total_ms | int | None | Preparation + queue + NDI processing + active result preparation. |
first_response_ms | int | None | For Parse, time to the first usable server-published preview; equals the known total when the server confirms no preview was published. Other document kinds use the final total. None when unavailable. |
breakdown | DocumentTimingBreakdown | Stage measurements in milliseconds. |
| Member | Type | Description |
|---|
preparation_ms | int | None | Original handler receipt through authentication, admission and NDI job creation. |
queue_ms | int | None | NDI creation to processing start. |
ndi_processing_ms | int | None | NDI processing, including document finalization. |
result_preparation_ms | int | None | Active final-result request work, including internal transfer and settlement. |
delivery_wait_ms | int | None | Idle wait before that final read starts; excluded from the total. |
document_finalization_ms | int | None | All requested Parse previews published to NDI finish; always None for other document kinds. Already included in ndi_processing_ms. |
Each breakdown value is None until its endpoints are available and consistent: queue needs creation/start, NDI processing needs start/finish, result preparation needs finish/final response preparation, and document finalization needs preview publication/finish. delivery_wait_ms is None until completion. Successful atomic jobs may have no preview publication measurement, so document_finalization_ms can stay None. The job timing reference lists every field's availability; do not substitute zero for an unknown component.
| Member | Type | Description |
|---|
currency | Literal["USD"] | Dollar currency. |
pricing_version | str | Customer pricebook pinned at admission. |
total_usd | str | Recorded wallet charge in exact decimal USD. |
lines | tuple[DocumentCostLine, ...] | Measured components; empty for historical credit-priced jobs. |
| Member | Type | Description |
|---|
operation | Literal["parse", "split", "classify", "extract", "ground"] | The component priced. |
quantity | int | Page-equivalents or requested targets. |
unit | Literal["page", "target"] | The quantity's unit. |
execution | Literal["fresh", "reused"] | Fresh processing or verified reuse. |
unit_price_usd | str | Exact USD per unit. |
amount_usd | str | Exact USD for this line. |
reuse_reason | str | None | Why the work was reused; None for fresh work. |
DocumentCost and DocumentCostLine are in nace-sdk 0.4.0 and later. In 0.3.0, job.cost is the raw dictionary, also in model_extra["cost"]. Amounts are exact decimal strings: convert them with Decimal, not float.
| Type | Fields |
|---|
UploadedFile | workspace_id: str, file_id: str, path: str | None, plus the document service's other file fields. as_source() returns a WorkspaceFileSource. |
UploadGrant | workspace_id, upload_url (a document-service URL, not Drex's), token (send as X-Upload-Token), expires_at, max_bytes: int | None. |
UploadSession | workspace_id, session_id, session_token, chunk_size: int, total_parts: int, expires_at, upload_session_url. |
UploadSessionStatus | session_id, status (open, completing, completed or aborted), chunk_size, total_parts, parts (the landed parts, unordered, as {"part_number", "size_bytes"}), received_bytes, declared_size_bytes, expires_at. |
FileDeletion | object (always file_deletion), workspace_id, file_id, status (deleted or deleting). |
Each mirrors the API's object: a field the API reference doesn't mark required is None (or empty) when the response leaves it out, and fields the SDK doesn't name are in model_extra.
| Type | Fields |
|---|
Workspace | workspace_id: str, name: str, status: str (active, deleting, or in a list unavailable: a workspace the service no longer has, which you delete to drop), owner_user_id: str | None, access: dict[str, Any], domain_id: str | None, domain_slug: str | None, domain_version: int | None, storage: WorkspaceStorage | None (where it keeps its files; see below), config_version: int | None, created_at: str | None, updated_at: str | None. See Read a workspace. |
WorkspacePage | items: tuple[Workspace, ...], next_cursor: str | None (None on the last page), total_count: int. |
WorkspaceStats | files_total: int | None, bytes_total: int | None, files_by_ingestion_status: dict[str, int], pages_ingested: int | None, index_documents: int | None, last_ingestion_at: str | None, next_expiry_at: str | None, files_expiring_within_7d: int | None. |
| Type | Fields |
|---|
StorageConnection | id: str, name: str, destination: S3Destination | AzureBlobDestination, status: "draft" | "ready" | "degraded" | "revoked" | str, can_manage: bool (whether your key may change it), external_id: str (what your IAM role's trust policy must require), aws_trusted_principal_arn: str | None (older single trusted role), aws_trusted_principal_arns: tuple[str, ...] (every Nace role your trust policy must allow; empty for Azure), credentials_pending: bool, validation_running: bool, credential_generation: int, validated_at: str | None, reactivation_requires_approval: bool (Nace revoked it; only Nace support can let it be validated again), revoked_reason: str | None (owner, administrator, member_removed or user_disabled), revoked_at: str | None, created_at: str, is_ready: bool (True when a new workspace can be bound to it). See Read a storage connection. |
StorageConnectionPage | items: tuple[StorageConnection, ...], next_cursor: str | None (None on the last page). |
S3Destination | type: "s3", bucket: str, region: str, prefix: str (default ""). |
AzureBlobDestination | type: "azure_blob", account: str (the storage account name), container: str, prefix: str (default ""). |
S3SetupOptions | type: "s3", access_method: "auto" | "manual" | None (auto for the CloudFormation stack, manual to write the role yourself; Drex's default is auto), aws_account_id: str | None, role_name: str | None, kms_key_arn: str | None. |
AzureSetupOptions | type: "azure_blob", subscription_id: str | None, resource_group: str | None, tenant_id: str | None, client_id: str | None. |
StorageConnectionSetup | options: S3SetupOptions | AzureSetupOptions, trust_policy: str | None, permissions_policy: str | None, cloudformation_template: str | None, launch_url: str | None, role_arn: str | None (each S3 only, as JSON or a link), azure_cli: str | None (Azure only). See Read a connection's setup. |
AwsRoleCredential | type: "aws_role", role_arn: str. |
AzureServicePrincipalCredential | type: "azure_service_principal", tenant_id: str, client_id: str, client_secret: SecretStr (shown as **********; a str is accepted). |
WorkspaceStorage | type: "managed" | "tenant_bucket" | "external" | str, connection_id: str | None, provider: "s3" | "azure_blob" | str | None, location: str | None (the folder the workspace's files are kept in), health: "draft" | "ready" | "degraded" | "revoked" | str | None (the connection's status). For a workspace you were invited into, connection_id and location are None. |
The destination, setup option and credential types are what you pass to client.storage_connections; a field left None is not sent.
| Type | Fields |
|---|
DomainSummary | domain_id: str, slug: str, display_name: str, owner: "platform" | "tenant" | str, version: int, status: "draft" | "published" | str, parent_slug: str | None, class_count: int | None, selectable: bool (True once published). |
Domain | domain_id: str, slug: str, display_name: str, owner: "platform" | "tenant" | str, version: int, status: "draft" | "published" | str, parent_slug: str | None, class_count: int | None, selectable: bool, taxonomy: dict[str, Any] (classes and allow_other), published_at: str | None. See Read a domain. |
DomainValidation | valid: bool, errors: tuple[dict[str, Any], ...] (each {"code", "path", "message"}), effective_class_count: int | None. |
DomainWrite | domain: Domain, validation: DomainValidation. |
DomainPage | items: tuple[DomainSummary, ...], next_cursor: str | None (None on the last page), total_count: int. |
| Type | Fields |
|---|
WorkspaceFile | file_id: str, workspace_id: str, path: str, file_name: str | None, file_type: str | None, size_bytes: int | None, version: int | None, observed_hash: str | None, ingested_hash: str | None, ingestion_status: str | None, ingested_at: str | None, category: str | None, access_label: str | None, access_label_source: str | None, expires_at: str | None, labels: dict[str, str], created_at: str | None, updated_at: str | None. See Read a file. |
WorkspaceFilePage | items: tuple[WorkspaceFile, ...], next_cursor: str | None, total_count: int | None, coverage: dict[str, Any] | None (files the workspace's access labels kept from you). |
WorkspaceFileDetail | download_url: str | None, preview_url: str | None and download_url_expires_at: str | None, plus the same fields as WorkspaceFile. |
WorkspaceFileMetadata | file: WorkspaceFile | None, lane: str | None, page_count: int | None, sheet_names: tuple[str, ...] | None, duration_ms: int | None, summary: str | None, keywords: tuple[str, ...] | None, documents: tuple[dict[str, Any], ...] | None, sheets: tuple[dict[str, Any], ...] | None, media: dict[str, Any] | None, outputs: tuple[dict[str, Any], ...], representations: dict[str, Any], last_error: dict[str, Any] | None. See Read a file's metadata. |
WorkspaceFileVersion | version: int | None, size_bytes: int | None, observed_hash: str | None, ingested_hash: str | None, ingested_at: str | None, created_at: str | None, replaced_at: str | None (None on the current one), is_current: bool | None. |
WorkspaceFileVersionPage | items: tuple[WorkspaceFileVersion, ...], next_cursor: str | None. |
WorkspaceFileOutput | output_id: str | None, kind: str | None, path: str | None, generation: int | None (the file version it came from), created_at: str | None, download_url: str | None, preview_url: str | None, download_url_expires_at: str | None. |
WorkspaceFileOutputMembers | members: tuple[dict[str, Any], ...] (each with path, file_name, size_bytes, download_url and preview_url), total_count: int | None, download_url_expires_at: str | None. |
Search results are plain dicts in DocumentJob.result; their shapes are in the API reference's Automatic search and QA.
| Type | Fields |
|---|
JobEvent | sequence: int | None (the SSE id), at: str | None (ISO 8601), status: str | None, progress: dict | None (such as units_done, units_total, stage), message: str | None. |
JobRequest | request_type: str; the rest of the request in model_extra. |
FileLink | url: str (fetch it without your API key), expires_at: int (Unix seconds). |
RowsPage | path: str, start_row: int (row number of rows[0]), limit: int, total_rows: int, columns: tuple[RowsColumn, ...], rows: tuple[dict[str, str], ...] (cells keyed by column name). |
RowsColumn | name: str, data_type: str. |
| Type | Fields |
|---|
ExtractionSchema | schema_id (sch_...), name, description: str | None, version: int, owner ("account", or "platform" for one Nace provides), created_at, updated_at, schema_: dict | None (the JSON Schema; None on a list item). |
ExtractionSchemaList | items: tuple[ExtractionSchema, ...], next_cursor: str | None, total_count: int | None. |
nace_sdk.constants holds the environment variable names and defaults the client uses:
| Name | Value |
|---|
API_KEY_ENV | "NACE_API_KEY" |
BASE_URL_ENV | "NACE_BASE_URL" |
DEFAULT_MODEL_ENV | "NACE_DEFAULT_DECISION_MODEL" |
LOG_LEVEL_ENV | "NACE_LOG_LEVEL" |
CONFIG_PATH_ENV | "NACE_CONFIG_PATH", the saved-credentials file's location. |
WORKSPACE_ID_ENV | "NACE_WORKSPACE_ID", the workspace the CLI and MCP server use when a command names none. |
LEGACY_ENV | {"NACE_API_KEY": "DREX_API_KEY", "NACE_BASE_URL": "DREX_BASE_URL", "NACE_DEFAULT_DECISION_MODEL": "DREX_DEFAULT_MODEL", "NACE_LOG_LEVEL": "DREX_LOG_LEVEL", "NACE_CONFIG_PATH": "DREX_CONFIG_PATH"} |
DEFAULT_BASE_URL | "https://console.nace.ai" |
DEFAULT_MODEL | "drex-latest" |
DEFAULT_TIMEOUT | 60.0 seconds per HTTP attempt |
LEGACY_ENV maps each variable to its name before the packages were renamed from drex-*. read_env(name) returns the stripped value of name, else of its LEGACY_ENV name, and None when both are unset or blank; the SDK, CLI and MCP server read every variable through it.
nace_sdk exports the document and browser run constants and literal types itself:
| Name | Value |
|---|
DOCUMENT_OPERATIONS | ("parse", "split", "classify", "extract", "ground") |
JOB_STATUSES | ("queued", "running", "succeeded", "failed", "cancelled") |
TERMINAL_STATUSES | frozenset({"succeeded", "failed", "cancelled"}) |
MAX_WAIT_SECONDS | 60: the longest wait_seconds. |
MAX_ROWS_PAGE_SIZE | 100: the largest rows limit. |
UPLOAD_SESSION_THRESHOLD_BYTES | 33554432 (32 MiB): upload sends files this size or larger in parts. |
DocumentOperation | Literal["parse", "split", "classify", "extract", "ground"] |
JobStatus | Literal["queued", "running", "succeeded", "failed", "cancelled"] |
OnConflict | Literal["reject", "new_version"] |
BROWSER_RUN_STATUSES | ("queued", "running", "succeeded", "partial", "failed", "cancelled", "timed_out") |
BROWSER_RUN_FINAL_STATUSES | frozenset({"succeeded", "partial", "failed", "cancelled", "timed_out"}) |
BrowserRunStatus | Literal["queued", "running", "succeeded", "partial", "failed", "cancelled", "timed_out"] |
nace_sdk.__version__ is the installed version, as a string.