Skip to content

MinIO Outputs ​

The outputs field in a job request declares where final artifacts should be delivered in MinIO.

How it works ​

  1. You declare outputs in the job request, mapping artifact references to MinIO directories
  2. Ordo records the declarations in job_output
  3. Each step writes its artifact to the intermediate area, artifacts/job_{id}/{step_id}/
  4. Once every step has finished, the Job Finalizator copies each declared artifact into its declared directory, then marks the job success

Ordo does not move or write files. All storage operations are performed by n8n.

Delivery is all-or-nothing per job:

  • If any step failed, nothing is delivered, not even the outputs of steps that succeeded. The job ends partial, or failed when no step succeeded.
  • If a declared artifact was never produced, the job is marked partial.
  • Delivery is a copy. The intermediate artifact stays under artifacts/job_{id}/.
  • A folder artifact delivers only the objects written since the job was created. Anything older under the same artifacts/job_{id}/ prefix is not copied.

Format ​

json
"outputs": {
  "step:build_ept.output_ept": {
    "path": "development/results/piney-dam/ept"
  },
  "step:build_copc.output_copc": {
    "path": "development/results/piney-dam/copc"
  }
}

Keys are namespaced artifact references (must match a step: artifact produced by the recipe). Values have a single path field.

path is always a directory ​

The declared path is a directory, never a filename. You choose the directory. The executor chooses the name of what goes inside it.

  • The first segment of path is the MinIO bucket (development, production). The rest is the key prefix.
  • No leading or trailing slash.

Where the delivered bytes end up depends on whether the artifact is a file or a folder:

Artifact kindDelivered atExample (path = development/results/survey/copc)
File{path}/{delivered filename}development/results/survey/copc/output.copc.laz
Folder{path}/… — the folder's contents land directly under path; the folder's own name is droppeddevelopment/results/survey/ept/ept.json

A file artifact keeps its name and gains a directory level. A folder artifact loses its name and its contents take its place. You cannot predict the final key from path alone; you also need the delivered name from the table below.

Delivered names ​

The delivered filename is whatever name the executor gives its intermediate file. You cannot choose it or override it.

ExecutorOutput slotKindDelivered at
ASSIGN_PROJECTIONoutput_lasfile{path}/output.las
REPROJECT_LASoutput_lasfile{path}/output.copc.laz (when the step skips, the input file under its own name)
REGRID_LASoutput_lasfile{path}/output.las
COLORIZE_AS_DEMoutput_lasfile{path}/output.las
COLORIZE_FROM_TIFoutput_lasfile{path}/output.las
BUILD_COPCoutput_copcfile{path}/output.copc.laz
DATASET_INFOmetadatafile{path}/info.json
BUILD_COLORED_DSMcolored_dsm_tiffile{path}/colored_dsm.tif
BUILD_COLORED_HILLSHADE_DSMcolored_hillshade_dsmfile{path}/colored_hillshade_dsm.tif
BUILD_HILLSHADE_DSMhillshade_dsmfile{path}/hillshade_dsm.tif
BUILD_CONTOURScontours_mbtilesfile{path}/contours.mbtiles
BUILD_CONTOURScontours_pmtilesfile{path}/contours.pmtiles
BUILD_XYZ_TILESoutput_tilesfolder{path}/{z}/{x}/{y}.png
BUILD_EPToutput_eptfolder{path}/ept.json, {path}/ept-data/…, {path}/ept-hierarchy/…
BUILD_POTREEoutput_potreefolder{path}/metadata.json, {path}/octree.bin, {path}/hierarchy.bin, …
CALL_WEBHOOKnone—nothing delivered

These names are defined in each executor's n8n workflow, and a change there moves the delivered key. Don't build keys from this table. Read delivered_uri instead.

Reading the delivered key ​

After delivery, each entry in outputs carries the key that was actually written. It appears in GET /jobs/:id, GET /outputs?job_id=… and the on-exit webhook body:

json
{
  "artifact_name": "step:dataset_info.metadata",
  "path": "development/results/survey/metadata",
  "delivered_uri": "development/results/survey/metadata/info.json",
  "delivered_at": "2026-09-25T18:35:34.211Z"
}
  • path is what you requested. It never changes.
  • delivered_uri is {bucket}/{key} of the delivered file. For a folder output it is the directory prefix, ending in /.
  • Both delivered_uri and delivered_at are null until the output has been delivered. They stay null for jobs that end partial or failed.
  • The Finalizator records the key before it marks the job success and before the on-exit hook runs. A success job therefore always has them set.
  • Jobs finalized before this field existed (up to job 1000014 on prd) have null.

Path conventions ​

Give each declared output its own directory. Delivery overwrites without warning:

  • Two file outputs with the same delivered filename in the same directory overwrite each other. For example, two BUILD_COPC steps both write output.copc.laz.
  • A folder output shares its directory with anything else declared there, because its contents are copied directly into path.
  • Re-running a job with the same path overwrites the previous delivery.

The one safe exception is file outputs whose delivered names differ, such as BUILD_CONTOURS' contours.mbtiles and contours.pmtiles. They can share a directory.

A consistent layout:

{bucket}/results/{project}/{output_name}/
json
"outputs": {
  "step:build_copc.output_copc":   { "path": "production/results/survey/copc" },
  "step:dataset_info.metadata":    { "path": "production/results/survey/metadata" },
  "step:build_xyz_tiles.output_tiles": { "path": "production/results/survey/tiles" }
}

delivers:

production/results/survey/copc/output.copc.laz
production/results/survey/metadata/info.json
production/results/survey/tiles/{z}/{x}/{y}.png

Do not put a filename in path. "path": "development/results/survey/dataset.copc.laz" delivers to development/results/survey/dataset.copc.laz/output.copc.laz.

Known limitation: recipes that fan out ​

The Finalizator finds the artifact to deliver by its slot name (output_copc) alone and ignores the step:<id>. prefix. If a recipe has several steps that produce the same slot name (for example, three BUILD_COPC steps), their declared outputs cannot be told apart. They may all deliver the same file. Until this is fixed, do not rely on per-step outputs from fan-out recipes.

Optional ​

The outputs field is optional. If omitted, artifacts are still tracked in Ordo with their intermediate MinIO URIs (under artifacts/job_{id}/{step_id}/), but nothing is delivered.

You only need outputs if the downstream system needs to find the result at a known, stable MinIO path.