Auto-upload OrcaSlicer G-code to your library
Set up OrcaSlicer's post-processing hook so every export lands in a self-hosted library, and what it does not do: file the slice as a revision.
OrcaSlicer does not upload to a file library on its own. Its built-in upload targets a printer host such as Moonraker or OctoPrint, which puts the file on the machine and leaves nothing in a library behind it. The path that does work is post-processing scripts: OrcaSlicer runs a command after each export and appends the exported file’s path as the last argument, so a small script can push that file wherever you want. PrintStash ships one at scripts/printstash_orca_push.py.
The script logs in with a username and an API key, gets a JWT back, and posts the file to POST /api/v1/ingest/orca. It uses only the Python standard library, so there is nothing to install alongside it, and it always exits 0. A library that is down or unreachable never blocks your export.
Setting it up
Create the key first. Under Settings -> Access, add a named API key and copy it when it appears, because PrintStash shows it once. An API key is a login credential rather than a permanent token, and it can be revoked without touching your password, which is the reason the hook uses one.
Download the script somewhere stable:
curl -o ~/printstash_orca_push.py \ https://raw.githubusercontent.com/xiao-villamor/PrintStash/main/scripts/printstash_orca_push.pyThen open OrcaSlicer’s process settings, go to Others -> Post-processing scripts, and add one line:
/usr/bin/python3 /home/you/printstash_orca_push.py --url http://printstash.lan:8000 --username automation --api-key <api-key> --collection "Slices/Inbox"Every line in that box runs as a shell command with the G-code path appended, so use absolute paths for both the interpreter and the script. On Windows the interpreter and script paths need quoting: "C:\Python313\python.exe" "C:\Tools\printstash_orca_push.py" --url ....
Now slice something small and export it. Two things should happen: the file appears in the library within a few seconds, and ~/.printstash_orca_push.log records the upload. That log is where to look when nothing appears, because the script never reports failures back to the slicer. Network errors get three attempts with backoff. A 4xx answer stops immediately, which usually means a wrong key, an account without edit rights on the target collection, or a file extension the endpoint rejects.
What lands in the library, and what does not
Each upload is hashed, parsed for slicer metadata, and thumbnail-extracted in the background, so the entry arrives with the layer height, infill, material, estimated time, and filament figures OrcaSlicer wrote into the file. The entry is named after the exported file unless you pass --model-name.
Matching is by content hash only, which has a consequence most setup guides skip over. Identical bytes land on the entry that already holds them, as another version of that file rather than a second entry, but a different slice becomes a new entry, even when you pass the same --model-name for both. The hook does not attach the slice as a revision of the STL it came from, and it has no flag that would let it: the endpoint accepts a source_hash for that, and the shipped script never sends one.
What the hook gives you is an inbox. Treat it as one and it works well: send everything to a --collection "Slices/Inbox" with a tag, then file the slices worth keeping onto their source model afterwards. Attaching a revision is the one action that carries a label, an outcome, and the recommended marker anyway, and those are the fields that make a revision history worth having. In the interface that is the upload control on the model page; from a script it is POST /api/v1/models/{model_id}/gcode-revisions, which takes revision_label, revision_status, and is_recommended alongside the file.
If you want the automatic path to skip the inbox entirely, write your own hook against /api/v1/ingest/orca with source_hash set to the sha256 of the source mesh. That means your script has to know which mesh produced the slice, which OrcaSlicer will not tell it, so most people keep the shipped script and do the filing by hand.
Getting the file to the printer
From the library, open the model, pick the revision, and send it to a printer. Moonraker is the stable provider and takes an upload with or without auto-start, then reports measured duration and filament use when the job finishes. PrusaLink, OctoPrint, Bambu LAN, and Elegoo Centauri are beta and accept uploads with narrower capability sets. Elegoo upload still needs broader hardware validation, and its file inventory is disabled. The compatibility matrix has the current per-provider detail.
Whether that beats OrcaSlicer’s own send-to-printer depends on how often you reprint. For a calibration cube you slice once and never look at again, the direct path is shorter and the library entry is noise. For parts you reslice, the library keeps the record of which slice printed clean, and the printer keeps only a filename.
Two things worth deciding before you leave it running
The API key sits in the process preset, in plain text, in whatever the slicer stores and exports. If you share presets or move them between machines, give the hook its own key and revoke it when a preset leaves your control. The script also reads PRINTSTASH_URL, PRINTSTASH_USERNAME, and PRINTSTASH_API_KEY from the environment, which keeps the key out of the preset, though a GUI launch of OrcaSlicer does not always inherit the environment your shell exports. A one line wrapper script that sets the variables and calls the hook is the reliable version of that idea.
The second is volume. A hook that fires on every export files every export, including the eleven attempts at a first layer. Nothing prunes those for you. A dedicated inbox collection makes the cleanup a filter and a multi-select instead of an archaeology session.
Questions that come up
Does OrcaSlicer upload to a file library by default?
No. OrcaSlicer’s built-in upload is a print host upload, which sends the file to a Moonraker, OctoPrint, or similar instance so it can be printed. There is no built-in target for a file library or a NAS folder. Every automatic path into a library goes through post-processing scripts, which is a general mechanism: OrcaSlicer runs your command after each export and hands it the exported file’s path. What that command does with the file is entirely up to the script.
Does an auto-uploaded slice become a revision of its source model?
Not with the shipped hook. The ingest endpoint matches uploads to existing entries by content hash, so a new slice with different bytes becomes its own library entry rather than a revision of the STL it was sliced from, and passing the same --model-name does not change that. Attaching a revision to a specific model is a separate action, either the upload control on the model page or POST /api/v1/models/{model_id}/gcode-revisions. That path is also where revision labels, outcomes, and the recommended marker live, so it is worth doing deliberately rather than automating badly.
What happens if PrintStash is down while I slice?
Your export finishes normally. The script always exits 0, because a post-processing script that fails is a post-processing script that breaks slicing, and no library is worth that. It retries transient network and server errors three times with backoff, gives up quietly, and writes the reason to ~/.printstash_orca_push.log. The consequence is that failures are silent: if you rely on the hook, check that log the first time a file does not turn up rather than assuming the upload happened.
Can I use the same hook from PrusaSlicer or Bambu Studio?
Yes. The script only needs a file path as its last argument, and both slicers pass one to post-processing scripts the same way OrcaSlicer does, since all three inherit the mechanism from Slic3r by way of PrusaSlicer. The endpoint name says orca but it accepts G-code from any of them, and the metadata parser handles OrcaSlicer, PrusaSlicer, Bambu Studio, and Cura output, with the usual caveat that which fields appear depends on what the slicer wrote. Binary .bgcode from PrusaSlicer is parsed for metadata and thumbnails, but cannot be previewed as toolpaths or sent to a printer.
Do I need a printer connected for any of this?
No. The hook, the metadata parsing, the collections, and the revision history all work with no printer configured, and setting print outcomes by hand takes a few seconds while you are still holding the part. Connecting a printer adds sending from the library, job history attached to the revision, and, on Moonraker, measured duration and filament instead of slicer estimates.
Sources
- Post-processing scripts in the OrcaSlicer wiki for where the setting lives and how commands are written, and the Prusa Knowledge Base article for the shared mechanism: the G-code path is passed as the last argument, and scripts run before the file is written out or sent to a print host. Both checked August 12, 2026.
- OrcaSlicer integration in the Mainsail docs for the direct upload-to-printer path this replaces.
- PrintStash user guide and API reference, plus
scripts/printstash_orca_push.pyin the repository.
Once slices are arriving on their own, tracking G-code revisions covers what to do with them, and using the API for automation has the login flow if you would rather write your own hook. For the printer end, connecting Klipper through Moonraker is the setup that gives you measured results back.