# Read and list jobs

Source: https://convergingthought.com/docs/api-reference/jobs

> GET /v1/jobs/{id} and GET /v1/jobs — durable outcomes, usage, and settlement.



Listing project jobs requires `read`. A key with `inference` or `internalize` can read individual jobs that it submitted under that scope. Other keys need `read` within the same selected tenant to inspect them. A job belongs to the project selected by the API key. Reading an unknown or another project's job returns `not_found` rather than disclosing cross-project state.

For customer-scoped jobs, repeat `X-Internalize-Tenant` on list and detail reads, or use a key restricted to that tenant. An omitted header on an unrestricted key selects only the project namespace. Responses include `tenant_id` (`null` for project memory); knowledge from another tenant is never returned. See [Serve multiple customers](/docs/guides/multitenancy).

## Read a job [#read-a-job]

```bash
curl --fail-with-body "$INTERNALIZE_BASE_URL/v1/jobs/YOUR_JOB_ID" \
  -H "Authorization: Bearer $INTERNALIZE_API_KEY"
```

The response is the job object directly. This example is illustrative, with placeholder identifiers and usage:

```json
{
  "id": "YOUR_JOB_ID",
  "subject_id": "support-policy",
  "kind": "inference",
  "status": "succeeded",
  "phase": "complete",
  "adapter_version": "YOUR_VERSION_ID",
  "usage": {
    "input_tokens": 120,
    "output_tokens": 80,
    "cached_input_tokens": 0,
    "training_tokens": 0
  },
  "billing": {
    "reserved_microusd": 25000,
    "charged_microusd": 3840,
    "settled": true,
    "pricing_version": "2026-09-27",
    "compute_microusd": 3840,
    "storage_microusd": 0
  },
  "result": { "text": "ILLUSTRATIVE_ANSWER", "finish_reason": "stop" },
  "error": null,
  "created_at": "2026-09-24T10:00:00.000Z",
  "updated_at": "2026-09-24T10:00:08.000Z"
}
```

## Fields [#fields]

| Field                       | Meaning                                                       |
| --------------------------- | ------------------------------------------------------------- |
| `id`                        | Durable job ID returned by admission                          |
| `subject_id`                | The subject name supplied by the caller                       |
| `kind`                      | `inference` or `internalization`                              |
| `status`                    | Machine-readable lifecycle state                              |
| `phase`                     | Diagnostic execution phase; do not treat it as a percentage   |
| `adapter_version`           | Version resolved at admission, or `base`                      |
| `usage.input_tokens`        | Recorded inference input tokens                               |
| `usage.output_tokens`       | Recorded inference output tokens, including reasoning         |
| `billing.reserved_microusd` | Original reservation, retained for inspection                 |
| `billing.charged_microusd`  | Settled charge; inspect `settled` before treating it as final |
| `billing.settled`           | Whether the reservation has been settled                      |
| `result`                    | Operation-specific result, or `null`                          |
| `error`                     | Job error code and retryability, or `null`                    |
| `created_at`, `updated_at`  | ISO UTC timestamps                                            |

For learning, `adapter_version` is the parent. The candidate appears under `result.candidate.version_id`. Validation uses `passed`, `passed_count`, and `total_count`; activation uses `activated` and `activation_conflict`.

Result objects can contain additional diagnostic fields. Read the known fields you need without assuming every operation has `text` or every unsuccessful job has a candidate. Do not expose an entire result object publicly without considering the model content it contains.

## Status handling [#status-handling]

| Status                    | Interpretation                             | Next step                          |
| ------------------------- | ------------------------------------------ | ---------------------------------- |
| `queued`                  | Admitted, waiting for execution            | Poll                               |
| `running`                 | Worker executing                           | Poll with backoff                  |
| `succeeded`               | Inference completed                        | Read the answer and settlement     |
| `ready`                   | Learning candidate saved and validated     | Inspect activation outcome         |
| `rejected`                | Learning validation rejected the candidate | Review source and evaluation       |
| `failed`                  | Known terminal error                       | Read error and settled charge      |
| `reconciliation_required` | Outcome or usage remains ambiguous         | Preserve ID; request investigation |

The public job error currently reports `retryable: false`. This is distinct from an HTTP error's retryability. Do not build a generic “retry all failures” button that resubmits paid work with a new key.

## List jobs [#list-jobs]

```bash
curl --fail-with-body --get "$INTERNALIZE_BASE_URL/v1/jobs" \
  -H "Authorization: Bearer $INTERNALIZE_API_KEY" \
  --data-urlencode "limit=50"
```

List items contain only `id`, `kind`, `status`, `phase`, `adapter_version`, and `created_at`. Fetch the individual job for subject, answer, validation, usage, or billing details.

```json
{ "data": [], "next_cursor": null }
```

Results are newest first. `limit` defaults to 50 and accepts integers from 1 to 100. When `next_cursor` is non-null, send it as the `cursor` query parameter using URL encoding. Continue until `null`. There are no public server-side kind, subject, date, or status filters in this endpoint.

Pagination is for discovery and history, not a replacement for saving admission receipts. Persist the job ID immediately and poll it directly. See [Requests in the console](/docs/product/requests) for the corresponding inspection interface.

## Price and usage details [#price-and-usage-details]

`usage.cached_input_tokens` is a subset of input tokens. `usage.training_tokens` counts every billed training exposure. Learning input/output include teacher, scoring, and evaluation calls. `billing.pricing_version` is fixed at admission; `compute_microusd` and `storage_microusd` break down the settled charge. Missing or inconsistent provider receipts leave the request in reconciliation.
