Are you an LLM? Read llms.txt for a summary of the docs, or llms-full.txt for the full context.
Skip to content

GET /result/

Poll for the result of an async job started by POST /explain/async. Polls collect what you already owe; the first poll after the job finishes charges the true-up.

URL: https://mpp.oculr.xyz/result/:jobId

Auth: Every poll collects what the analysis has accrued since your previous poll - it answers 402 for that amount, and a poll with nothing yet to collect is free. The first poll after the job finishes charges the fee-bearing true-up, so the cumulative total (submit charge + polls + true-up) equals the sync SSE price exactly. An mppx client pays every one of them transparently; subsequent fetches of an already-paid finished result are free. Failed jobs true up the same way.

Request

Parameters

ParamTypeRequiredDescription
jobIdUUID (path)yesThe jobId returned by POST /explain/async.

Response

200 OK

{
  "jobId": "550e8400-e29b-41d4-a716-446655440000",
  "status": "complete",
  "result": { /* ExplanationResult - see POST /explain */ }
}
FieldTypeNotes
jobIdUUIDEchoes the request.
status"pending" | "running" | "complete" | "error"Transitions in order.
resultExplanationResultPresent only when status === "complete". Schema documented in POST /explain → Response.
errorstringPresent only when status === "error".
errorCodestringPresent when the error has a stable code, e.g. upstream_payment_unavailable.
htmlstringPresent when the job was started with report: true - a self-contained HTML report.

Examples

TypeScript

// `Mppx.create()` must be active - fetch() auto-pays whatever this poll collects.
const job = await fetch(`https://mpp.oculr.xyz/result/${jobId}`).then(r => r.json())
if (job.status === 'complete') return job.result
if (job.status === 'error')    throw new Error(job.error)
// else still pending or running - poll again

Shell (mppx CLI)

mppx https://mpp.oculr.xyz/result/$JOB | jq '{status, summary: .result.summary}'

Polling loop

while (true) {
  await new Promise(r => setTimeout(r, 5000))
  const job = await fetch(`https://mpp.oculr.xyz/result/${jobId}`).then(r => r.json())
  if (job.status === 'complete') return job.result
  if (job.status === 'error')    throw new Error(job.error)
}

Errors

CodeWhen it happensBody
402Accrued metered cost is owed before this poll is answered - mid-run or on the finished result. mppx clients handle it automatically.Standard MPP/x402 challenge.
404Job expired (TTL 1 hour) or jobId is unknown.{ "error": "Job not found - expired or invalid ID" }

Errors raised during analysis are surfaced via the status: "error" response, not via an HTTP error code. Check job.errorCode === "upstream_payment_unavailable" for the same outbound-payment failure documented on POST /explain.

Related