je-testing

Run journal-entry testing over a workspace's ledger package. Cost class: job.

The caller receives a 202 with a queued :class:~ndi_service.app.platform_api.results.Job immediately and polls GET /jobs/{id} for the :class:~ndi_service.app.platform_api.results.JetResult.

The agent orients itself in the tables the workspace holds, writes SQL over them itself, and answers with sql_receipts: every statement it ran, the tables each one registered (path, tab, and the view name the SQL used), and a bounded result. A figure in the answer is meant to be readable out of one of those receipts, and a receipt carries everything needed to re-run it.

paths scopes the run to exactly the files of the package under test; path_prefix scopes it to a folder, and the two add up: the run tests the folder's files plus the named ones. Omit both to test the whole workspace: the agent orients over every queryable file the caller can see and finds the ledger package itself, the same way deep-search behaves when unscoped. A run keeps its conversation: pass the result's session_id on a later request to ask a follow-up in the same thread.

reasoning_effort controls the thinking budget without changing the engine. Omit it for the route's default; null keeps the catalogue prescription.

allow_clarification lets the agent stop and ask instead of answering — early, for what the data cannot tell it (a threshold, the period or entity in scope, the client's definition of a term), or mid-run, for an ambiguity the work turned up. The succeeded result then carries the questions in clarification_questions with answer null. Answer them on the same session_id with the same query and clarification_answers, or with any follow-up query. Off (the default) the agent never asks.

exhausted: true means the step budget ran out before the procedure finished — a successful, partial response, not a failure.

post/v1/workspaces/{workspace_id}/je-testing

Request

Path parameters

workspace_idstring uuid required

Workspace identifier.

Query parameters

wait_secondsinteger

Bounded inline wait. 0 (the default) returns 202 immediately. Above 0 the route returns 200 with a terminal job if the work finished in time, and 202 with the still-running job if it did not. Either way, read status. Waiting does not change how an admitted job is counted and takes no max_concurrent_sync slot (that limits synchronous calls such as the legacy synchronous API and /v1/systemone). For retained jobs, the deployment may shorten the wait and return 202 with the running job; poll GET /v1/jobs/{job_id}. For parse, split, classify, categorize, extract and ground, a zero_retention tenant must pass wait_seconds above 0.

Headers

Idempotency-Keystring nullable

Use the same key to recover an earlier request. A replay returned as a Job carries Idempotent-Replayed: true and replayed: true without a new charge; Job credits keeps the original cost. Re-serving a settled inline tool answer reports zero credits for that call and also carries Idempotent-Replayed: true; a fresh re-execution after a transient failure carries no header. The key is kept with the job for replay and never cleared, so it must not contain personal data.

Request body

allow_clarificationboolean

Let the agent stop and ask instead of answering, when the test needs something the data cannot tell it (a threshold, the period or entity in scope, the client's definition of a term) or the work turns up a material ambiguity the request does not settle. The result then carries the questions in clarification_questions (and as text in clarification), with answer null; answer them in the same thread via the result's session_id, with clarification_answers or a follow-up query. Off, the default, means the agent always answers, naming the assumptions it made.

contextstring nullable

Free-form background for the model — the engagement, the entity, what the caller already knows. It informs the answer; it does not widen or narrow which files the caller may see.

effort'high' | 'medium' | 'low' nullable

Deprecated and ignored: the service resolves the run's configuration itself. Accepted so clients released before the effort levels were retired keep working; omit it.

path_prefixstring nullable

Put every uploaded file under one folder subtree, workspace-relative, in the run's scope; paths, where the body takes it, adds more files. Omit both for the whole workspace.

pathsstring[] nullable

Scope the run to exactly these uploaded files — the ledger package to test. Every tool the agent runs (listings, reads, SQL) sees only these files and the content ingested from them. Each entry names an uploaded source file, never a folder; scope folders with path_prefix, which adds its files to these. No limit on how many. Unknown or inaccessible paths are refused up front. Omit to test the whole workspace: the agent then orients over every queryable file the caller can see and finds the ledger package itself, exactly as deep-search does when unscoped.

querystring required

What to answer, in the caller's own words. Stripped before its length is checked; a blank query is refused rather than run.

reasoning_effort'none' | 'minimal' | 'low' | 'medium' | 'high' nullable

Thinking budget for the testing agent; changing it does not change the engine. Null keeps the catalogue's per-model prescription. The console's Effort pill sends 'low' (default) or 'medium'.

selection_idstring uuid nullable

Confirmed ledger source selection; mutually exclusive with path selectors.

session_idstring uuid nullable

Continue a prior je-testing conversation: the id echoed on an earlier result's session_id. The agent resumes with that thread's full context — its orientation and its receipted statements — and treats this request as the follow-up. Omit to start a new thread. Only the API key that started the thread may continue it; a thread whose turn is still running returns 409 session_busy.

Response

Terminal job or idempotent replay of the original job; read status and replayed.

created_atstring date-time required

When the job row was created.

credit_schedule_versioninteger nullable

Version of the credit schedule credits were priced under. Null until usage_final is true.

creditsinteger nullable

Final credits billed for this job, priced once under credit_schedule_version. Null until usage_final is true. Never changes afterwards, including after payload expiry or deletion. Failed and cancelled-before-completion jobs finalize with 0 credits, including delivered parts; ones finalized before that policy keep their credits. Always null on a stage job that Automatic Search delegated: its work is billed on the parent job.

deleted_atstring date-time nullable

When the caller hid this run from listings, via delete_job. A soft delete: the job still reads by id and still counts toward GET /v1/usage — what it stops doing is appearing in GET /v1/jobs.

effortstring nullable

How hard this run worked, for the search kinds that carry it. A deep-search job (kind deep_search_v2) created before the effort knob was removed echoes its requested level: 'low', 'medium', or 'high'; newer deep-search jobs, which all run one configuration, read null. An intelligent_search row carries an internal selector instead: 'fast' is fact-search, 'automatic' is automatic-search, and 'deep' (or the legacy 'balanced') is a deep-search or console QA chat job created before the 2026-09 consolidation — those two are not distinguishable by this field. Null for every other kind. Read from the stored request, so it rides the same retention path as query and result: null once result_state leaves available.

finished_atstring date-time nullable

When the job reached a terminal status.

forceboolean nullable

The request's own force flag, echoed regardless of outcome. Present for kinds whose request carries one (e.g. kg_build, where a true value cleared the durable store before the job ran) so a caller can tell that apart from a build that failed leaving the prior store untouched — result alone cannot, since it is absent on failure either way.

idempotency_keystring nullable

Key that was replayed to return this job. Absent when the create call had no Idempotency-Key.

job_idstring uuid required

Server-minted id. Poll GET /v1/jobs/{job_id} or pass wait_seconds on create.

kind'parse' | 'split' | 'classify' | 'categorize' | 'extract' | 'ground' | 'ingestion' | 'reconciliation' | 'kg_build' | 'file_upload' | 'file_replace' | 'upload_session_complete' | 'file_delete' | 'files_delete' | 'workspace_delete' | 'intelligent_search' | 'folder_metadata' | 'file_metadata' | 'read_file' | 'hybrid_search' | 'grep' | 'run_sql' | 'locate' | 'qa_file' | 'qa_tables' | 'filtered_search' | 'je_testing' | 'je_testing_v2' | 'deep_search_v2' | 'automatic_agent' | 'ledger_understanding' | 'ledger_understanding_reset' | 'ledger_parse_exhibits' | 'tenant_purge' | 'storage_connection_validate' required

What a job is doing. Open enum — a new member is additive.

namestring nullable

Display name (the console's 'project'). Public Parse, Split, Classify, Extract, and Ground runs supply a stable server default when blank; citation-generated Ground jobs are excluded. mutable via PATCH /v1/jobs/{job_id}.

payload_expires_atstring date-time nullable

Cleanup deadline after explicit deletion. Null for retained content; Zero retention uses its delivery window.

project_idstring uuid nullable

Caller-minted grouping id shared by jobs submitted together. Filterable on GET /v1/jobs.

querystring nullable

The question this job was asked, for the search kinds that carry one (intelligent_search, qa_file, qa_tables, filtered_search); null for every other kind. Read from the stored request, so it rides the same retention path as result: null once result_state leaves available. Narrow by design — the frozen access context never reaches the wire. File scope is summarised separately as query_scope.

replayedboolean

True only on an idempotent replay response. No new charge is made; credits remains the original job's cost.

result_state'available' | 'expired' | 'not_retained' | 'cancelled' | 'storage_unavailable'

Why Job.result is null.

available with a null result means the job has not succeeded yet; expired means its content was removed; not_retained means the client is provisioned zero_retention and already had its one chance to read it; cancelled means the job, or the root job it ran for, was cancelled. A cancelled job serves no results (it is not charged, including delivered parts) — not its own progressive values, and not a delegated child's result. It is a read state only, derived on the wire; no row stores it. storage_unavailable withholds a retained result while its workspace binding refuses access; Job.result_error explains the current refusal. A late poll returns the job with a state, never a 404 — "this expired" and "this never existed" are a scheduling problem and a bug respectively, and a 404 makes them identical.

started_atstring date-time nullable

When execution began. Null while still queued.

status'queued' | 'running' | 'succeeded' | 'failed' | 'cancelled' required

cancelled is a first-class terminal status, not a failed variant.

Conflating them makes error-rate metrics lie and forces every client to string-match an error code.

surface'deep_search' | 'qa' | 'workbook' nullable

Which console history this deep-search job belongs to. deep_search is the public route and the Deep Search page; qa and workbook are the console chat skins over the same agent. It does not pick the implementation. Null for fact-search and every non-deep-search kind. Jobs stored before this field existed echo deep_search. Read from the stored payload, so it rides the same retention path as query.

unitsinteger

Measured work in legacy credit units, retained even when a failed or cancelled job is not billed. Kept for compatibility: credits is the authoritative billed amount.

usage_finalboolean

True once credits is final and will not change. False while the job is queued or running, and until any cleanup of its delegated stages has been accounted for. A failed tool job (read_file, run_sql, hybrid_search, grep, file_metadata, folder_metadata) created with an Idempotency-Key stays false for one hour after it fails, because a retry with the same key re-runs it; after that hour it is final and the retry returns the stored error.

usage_finalized_atstring date-time nullable

When credits became final. Null until usage_final is true.

workspace_idstring uuid nullable

The workspace this job reads. Null for a document operation whose source is an upload, a URL, or a prior parse result.

Changes

    • info

      added the optional property to the response with the status

    • info

      added the success response with the status