Skip to main content

Response types

Every method that talks to the API hands you back a typed object, not a bare dict. These objects give you attribute access and autocomplete over the shapes the API returns: a chat completion's choices, a task match's type, an eval run's cost. They are thin: each one wraps the raw server JSON and exposes the fields you actually use as properties.

This page is the field-by-field reference for those objects. For how the methods that return them work, see Running inference, tasks, and Evaluating models.

The shared base: every object keeps the raw JSON​

All response objects inherit from one base. Two things are true of every object on this page:

  • .to_dict() returns the exact JSON the server sent, losslessly. The typed properties are a convenience layer over it; nothing is dropped.
  • obj["some_key"] and obj.get("some_key", default) read raw fields directly. This is the escape hatch for any field the platform adds before the typed layer catches up.
from pareta import Pareta

pa = Pareta.from_env() # reads PARETA_API_KEY (+ optional PARETA_BASE_URL)

resp = pa.chat.completions.create(
model="auto",
messages=[{"role": "user", "content": "ping"}],
)

resp.choices[0].message.content # typed access
resp.to_dict() # the full raw JSON, lossless
resp["id"] # raw-key access for anything not yet typed

Properties return None (or an empty list) when a field is absent rather than raising, so reading an optional field is always safe.

Inference types​

These come back from chat.completions.create (route POST /v1/chat/completions). Inference is OpenAI-compatible, so the schema matches the OpenAI chat objects.

ChatCompletion​

The non-streaming result of chat.completions.create(...).

PropertyTypeNotes
idstr | NoneCompletion id
modelstr | NoneThe model id on the completion
createdint | NoneUnix timestamp
choiceslist[Choice]One entry per generated choice
usageUsageToken counts
resp = pa.chat.completions.create(
model="auto",
messages=[{"role": "user", "content": "Extract the effective date."}],
temperature=0,
)
print(resp.choices[0].message.content)
print(resp.usage.total_tokens)

ChatCompletionChunk​

One delta from a streaming completion. Returned (one per SSE event) when you pass stream=True. It has the same schema as ChatCompletion; it is a distinct type purely for hinting. The incremental text lives on choices[0].delta.content, not choices[0].message.

for chunk in pa.chat.completions.create(
model="auto",
messages=[{"role": "user", "content": "Summarize this contract."}],
stream=True,
):
print(chunk.choices[0].delta.content or "", end="", flush=True)

The or "" guard matters: the first and last chunks often carry no content (role preamble, finish marker), so delta.content can be None mid-stream.

Choice​

One element of completion.choices.

PropertyTypeNotes
indexint | NonePosition in the choices list
finish_reasonstr | None"stop", "length", etc.
messageMessageThe full message. Populated on non-streaming results
deltaMessageThe incremental token. Populated on streaming chunks

message and delta always return a Message (empty if absent), so reading choice.delta.content on a non-streaming result, or vice versa, returns None rather than blowing up.

Message​

The content of a Choice.

PropertyTypeNotes
rolestr | None"assistant", "user", etc.
contentstr | NoneThe text

Usage​

Token accounting on a ChatCompletion.

PropertyType
prompt_tokensint | None
completion_tokensint | None
total_tokensint | None

Model listing types​

Returned from models.list() (route GET /v1/models). This is the OpenAI-compatible model listing: it returns exactly one entry, "auto", so any OpenAI-style tooling pointed at Pareta gets a sensible /models response with the one id you send.

ModelList​

PropertyType
datalist[Model]

ModelList is directly iterable and has a length, so you usually skip .data:

models = pa.models.list()
print(len(models))
for m in models: # iterates m in models.data
print(m.id, m.owned_by)

Model​

One element of a ModelList.

PropertyTypeNotes
idstr | None"auto". Pass straight into chat.completions.create(model=...)
owned_bystr | None"pareta"
createdint | NoneUnix timestamp

Scoring types​

These come from the tasks namespace and describe how your data will be scored before you send traffic.

Task​

Returned from tasks.list() and tasks.retrieve(id). One benchmarked job.

PropertyTypeNotes
idstr | NoneStable task id, e.g. "contract-key-fields"
default_scorerstr | NoneThe function that grades model output for this task
has_blob_inputboolTrue when the task takes documents or images, not just text
for t in pa.tasks.list():
print(t.id, t.default_scorer, "doc" if t.has_blob_input else "text")

has_blob_input tells you whether you will need evals.sets.upload_document(...) to attach binaries when you evaluate on this task.

TaskMatch​

Returned from tasks.match(query, top_k=...). The ranked result of matching a free-text description to a task.

PropertyTypeNotes
querystr | NoneThe query, echoed back
typestr | None"task", "capability", "unsupported", or "none"
matchedboolTrue when a high-confidence match was found
chosenTaskMatchCandidate | NoneThe best candidate, or None if nothing matched confidently
capabilityCapability | NoneThe general lane, when type == "capability"
candidateslist[TaskMatchCandidate]Top-K ranked alternates
reasoningstr | NoneThe router's rationale (reasoning matcher only)
confidencestr | None"high" / "medium" / "low" (reasoning matcher only)
ambiguousboolTrue when the top two scores are close
matcherstr | NoneWhich strategy answered: "reason" (LLM router) or "keyword" (fallback)
m = pa.tasks.match("pull totals and dates out of vendor invoices", top_k=5)
if m.type == "task" and m.chosen:
print("best:", m.chosen.task_id, m.chosen.score, m.chosen.confidence)
elif m.type == "capability" and m.capability:
print("capability:", m.capability.id, m.capability.label)
else:
print(m.type, "—", m.reasoning) # "unsupported" / "none"
print("via", m.matcher)

See tasks.match for the full matching semantics.

Capability​

The general capability lane a match resolved to — on TaskMatch.capability when TaskMatch.type == "capability".

PropertyTypeNotes
idstr | NoneThe lane id (chat/coding/agentic/vision/asr/tts)
labelstr | NoneHuman-readable label
categorystr | NoneCatalog category name
category_idstr | NoneCatalog category id
descstr | NoneOne-line description

TaskMatchCandidate​

An element of match.candidates (and the type of match.chosen).

PropertyTypeNotes
task_idstr | NoneThe candidate task's id
scorefloat | NoneMatch score in [0, 1]
confidencestr | None"high", "medium", or "low"

FrontierModel​

Returned from evals.frontier_models(task=...). A vendor model you can evaluate against — the baseline "auto" is measured by.

PropertyTypeNotes
idstr | NoneVendor model id. Feed into evals.runs.create(frontier=[...])
vendorstr | None"openai", "anthropic", etc.
visionboolTrue if vision-capable
benchmarkedboolTrue if it is benchmarked on the task. Only meaningful when you passed task=

Frontier ids are shown in the clear because they are public products. The open specialists auto routes to are not — they never surface as ids.

for fm in pa.evals.frontier_models(task=eval_set.task_id):
flag = "vision" if fm.vision else "text"
note = " (benchmarked on this task)" if fm.benchmarked else ""
print(fm.id, fm.vendor, flag, note)

Audio types​

The Speech lanes (asr, tts) return these from the audio namespace.

Transcription​

Returned from audio.transcriptions(audio, language=...). Speech-to-text.

PropertyTypeNotes
textstr | NoneThe transcript (also str(transcription))
languagestr | NoneDetected (or supplied) language
duration_sfloat | NoneInput audio length, metered per minute
t = pa.audio.transcriptions("call.wav") # path | bytes | base64
print(t.text, t.language, t.duration_s)

Speech​

Returned from audio.speech(text, voice=...). Text-to-speech.

PropertyTypeNotes
audiobytesThe synthesized audio, base64-decoded
audio_base64str | NoneThe raw base64 the server returned
sample_rateint | NoneSample rate of the audio
duration_sfloat | NoneOutput audio length, metered per minute
formatstr | NoneContainer/codec (e.g. "wav")

save(path) writes the decoded bytes to a file and returns self.

pa.audio.speech("Hello from Pareta.").save("out.wav")

Evaluation types​

These come from the evals namespace and carry the cost numbers you compare "auto" against the frontier with.

EvalSet​

Returned from evals.sets.create(...), evals.sets.list(), and evals.sets.retrieve(id). A reusable evaluation dataset.

PropertyTypeNotes
idstr | NoneEval set id. Pass to evals.runs.create(eval_set=...)
task_idstr | NoneThe task this set is graded against
namestr | NoneLabel (auto-generated if you did not pass one)
item_countint | NoneNumber of rows
scoring_strategystr | NoneThe strategy used to grade rows, e.g. "extraction", "classification"
es = pa.evals.sets.create(
prompt="extract the key fields from each contract",
items=[{"input": {"contract_text": "...contract..."}, "expected_output": {"effective_date": "2026-01-01"}}],
name="my contracts v1",
)
print(es.id, es.task_id, es.item_count, es.scoring_strategy)

EvalRun​

Returned from evals.runs.create(...), evals.runs.retrieve(id), and evals.runs.wait(id). The state of an evaluation, including per-model results once it is terminal. The object wraps the server's {"run": {...}, "results": [...]} envelope and flattens it for you.

PropertyTypeNotes
idstr | NoneRun id
eval_set_idstr | NoneThe set being evaluated
statusstr | None"running", "evaluating", "completed", "failed"
is_terminalboolTrue when status is "completed" or "failed"
candidate_modelslist[str]The candidates evaluated: "auto" and any frontier ids
error_detailstr | NoneFailure message when status == "failed"
cost_micro_usdintRaw total cost in micro-USD
costDecimalBilled total in dollars, floored to cents. See money
resultslist[EvalResult]Per-model aggregates (populated once terminal)
run = pa.evals.runs.create(
prompt="extract the key fields from each contract",
items=[{"input": {"contract_text": "..."}, "expected_output": {"effective_date": "2026-01-01"}}],
models=["auto"], # the product under test
frontier="benchmarked", # vendor baselines benchmarked on this task
wait=True, # block until terminal
)

if run.status == "failed":
print("eval failed:", run.error_detail)
else:
for r in sorted(run.results, key=lambda r: r.quality_mean or 0, reverse=True):
print(r.model_id, r.kind, r.quality_mean, r.mean_cost_micro_usd, f"n={r.n_succeeded}")
print("billed:", run.cost, "| raw µUSD:", run.cost_micro_usd)

Eval compute is metered against your org balance (both the auto runs and any frontier baselines). An empty balance raises InsufficientCreditsError (402); top up in the browser, since the SDK never exposes balance or payment.

EvalResult​

One element of run.results: a single candidate's aggregate over the run.

PropertyTypeNotes
model_idstr | NoneThe candidate evaluated: "auto" or a frontier vendor id
kindstr | None"frontier" on vendor baseline rows; unset on "auto" rows
quality_meanfloat | NoneMean score in [0, 1]
quality_ci_lowfloat | None95% CI lower bound
quality_ci_highfloat | None95% CI upper bound
mean_cost_micro_usdint | NoneAverage per-item cost in micro-USD (not floored)
n_succeededint | NoneRows that scored without error
error_countint | NoneRows that errored

The point of a result row is the comparison: read quality_mean against the confidence interval to know whether "auto" genuinely matches the frontier on your data, and mean_cost_micro_usd to see what each call costs.

auto_row = next(r for r in run.results if r.model_id == "auto")

for r in run.results:
if r.kind != "frontier":
continue
matches = (
auto_row.quality_ci_high is not None
and r.quality_mean is not None
and auto_row.quality_ci_high >= r.quality_mean
)
print(f"{r.model_id}: q={r.quality_mean:.3f} at {r.mean_cost_micro_usd} µUSD/item"
f" — auto ({auto_row.quality_mean:.3f}) "
f"{'matches it within the CI' if matches else 'trails it'}")

Money: .cost vs .cost_micro_usd​

Money on these objects follows one convention (SDK_PLAN §6): the billed total is floored to whole cents, while sub-cent unit rates stay in micro-USD. The SDK floors rather than rounds, so it never overstates a charge.

Three fields, two representations:

  • run.cost is a Decimal in dollars, floored to cents. A 5 µUSD run reads Decimal("0.00"); a 420,715 µUSD run reads Decimal("0.42"). This is what the org is billed.
  • run.cost_micro_usd is the raw integer in micro-USD. 1_000_000 = $1.00. Use it when you need the exact charge below cent precision.
  • Per-item unit rates stay in micro-USD on purpose: result.mean_cost_micro_usd (and the cost_micro_usd on an auto.compare_frontier() result). Flooring a fraction-of-a-cent unit rate to whole cents would collapse it to zero and erase the auto-vs-frontier comparison that is the whole reason you ran the eval.
from decimal import Decimal

print(run.cost) # Decimal("0.42") — billed dollars, floored
print(run.cost_micro_usd) # 420715 — raw micro-USD
assert run.cost == Decimal("0.42")

# Convert any micro-USD unit rate to dollars yourself when you want to display it:
mean = run.results[0].mean_cost_micro_usd # e.g. 850 µUSD per item
print(f"${mean / 1_000_000:.6f} per item") # $0.000850 per item

Both inference and evals debit the org balance on success; an empty balance raises InsufficientCreditsError. The SDK only ever consumes credit and surfaces the 402; topping up is browser-only.

See also​

  • Running inference — ChatCompletion, streaming chunks, and the async iterator form
  • tasks — Task and TaskMatch in depth, and the dataset-to-proof flow
  • Evaluating models — building EvalSets, running evals, and reading EvalRun cost
  • Core concepts — the auto story, hidden hardware, and metering, end to end