jobs

What the run printed

Changed on

Returns the job's captured execution log. Fetched on demand: a log is a debugging artifact a caller wants occasionally, while GET /api/v2/jobs/{id} is polled to terminal on every run, so the log is a resource of its own rather than a field that would ride every one of those polls to be read at most once.

Captured whenever the worker reports its own outcome, success and failure alike, since a job that succeeds while producing the wrong thing is exactly what a failure-only log cannot explain. A run the platform or the provider killed — out of memory, a crashed worker, a timeout, a job past its maximum runtime — never gets that far, so it reaches a terminal status carrying no log at all. That is a real gap and worth stating: the failures a caller most wants a log for are the ones least likely to have produced one.

204 is the normal answer for a job with no log, and the cases behind it are deliberately not distinguished: this surface does not capture logs at all, the job has not finished, the job predates log capture, the run was killed before the worker could report one, capture was attempted and failed, or the job ran on the public demo deployment, which captures and stores the log like every other serverless deployment but withholds it on read, because that surface takes callers with no credential and a job id would otherwise be the only thing between one anonymous caller and another's run.

Because a 204 never says which of those it is, do not branch on the reason — but do note that one of them resolves itself. A job that has not finished may have a log once it does, so a caller that wants one reads again after a terminal status. A 204 on a job already in a terminal state is final, and so is a missing urls.logs; both mean stop asking.

Only jobs run on the serverless platform (a {deployment}.run.comfy.app host) have one today. An implementation that captures no logs must still serve this operation, answering 204 for every job it can read, so that the two answers stay distinct — Comfy Cloud does. A self-hosted deployment on a build predating this operation has not implemented it yet and will answer a routing 404 instead, which is the case job.urls.logs exists to keep a client out of: its absence says the surface has no logs at all, without a request.

Tied to the job's own retention: this 404s under the same conditions GET /api/v2/jobs/{id} does (unknown, not-yours, or past its retention deadline). Nothing ages a log out ahead of the job's own expires_at, so a job never outlives its log.

Live tailing is not offered here yet. When it is, it arrives on this same path under Accept: text/event-stream, leaving this JSON snapshot the default; its resume semantics will be defined then, against a capture that is incremental. Until then the SSE log event on GET /api/v2/jobs/{id}/events is the reserved live rail, and this is the authoritative snapshot it reconciles against.

get/api/v2/jobs/{id}/logs

Request

  • Base URL: http://127.0.0.1:8189
  • URL: http://127.0.0.1:8189/api/v2/jobs/{id}/logs
  • Auth: one of:
    • HTTP bearer
    • none

Path parameters

idstring required

Response

The captured log.

textstring required

The captured output.

truncatedboolean required

The BEGINNING of the captured output was discarded — text is the TAIL of a longer run. Implementations bound what they capture and store, so a workflow that prints megabytes keeps its last lines, where a failure normally is, instead of being dropped whole. True with an empty text means the log was captured and then shed entirely to fit. This describes the stored log, never the response: it does not mean a caller asked for part of one.

captured_atstring date-time required

When the run's output was read back off the worker.

completeboolean required

No further output will be appended to this log. Always true today, because a log is read back off the worker once, when the run ends, so a log that exists is already whole. Sent so that a surface which later captures output while a run is still going can say so, and a client written now against false keeps working when it does. false does not promise that more output will arrive, only that this snapshot may not be the last one.

Changes