Deliver — API-referanse

Send pictures on: upload connections and their queue, workflows, tether, denoise, newspaper deliveries, galleries and eventphotos.

API-referansen er på engelsk: den lages fra appens eget OpenAPI-dokument.

Send pictures on: upload connections and their queue, workflows, tether, denoise, newspaper deliveries, galleries and eventphotos.

99 operations. Generated from the application's own OpenAPI document.

GET /api/albums/download

Album download

curl -X GET http://127.0.0.1:9100/api/albums/download \
  -H "Authorization: Bearer $CULLING_API_TOKEN"

Responses

  • 200 — How far the album download has come

POST /api/albums/download

Download album

Body

FieldTypeRequiredDescription
connectionstringA SmugMug connection, for a SmugMug album.
folderstringyesA path. In an instance started with `--dir` it is in the instance's root: `/` is the root, and a path that leads out of it is refused (403).
linkstringyesA public Flickr album's link, or a SmugMug gallery link or node id.
originalsbooleanThe originals instead of Flickr's largest derived size or SmugMug's 4K.
photographerstringFor SmugMug: the folder under `folder` its pictures go into.
splitByTitlebooleanFor Flickr: one folder per photographer, from each title's first word.
curl -X POST http://127.0.0.1:9100/api/albums/download \
  -H "Authorization: Bearer $CULLING_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"link":"text","folder":"text"}'

Responses

  • 200 — Started: the album's pictures go into the folder, one folder per photographer when asked
  • 400 — Not an album link, no SmugMug connection, or a download is already going

DELETE /api/albums/download

Stop album download

curl -X DELETE http://127.0.0.1:9100/api/albums/download \
  -H "Authorization: Bearer $CULLING_API_TOKEN"

Responses

  • 200 — Stops after the picture being fetched

GET /api/best-of-year

The year's best

curl -X GET http://127.0.0.1:9100/api/best-of-year \
  -H "Authorization: Bearer $CULLING_API_TOKEN"

Responses

  • 200 — How far the pick has come

POST /api/best-of-year

Pick the year's best

Body

FieldTypeRequiredDescription
countnumber
eventDirstringyesA path. In an instance started with `--dir` it is in the instance's root: `/` is the root, and a path that leads out of it is refused (403).
forgetRejectionsbooleanStart the review loop again, forgetting what was deleted.
modelstringThe local model that looks at the shortlist; none: Vision alone.
shortlistnumberPictures the model looks at; four times the count when left out.
curl -X POST http://127.0.0.1:9100/api/best-of-year \
  -H "Authorization: Bearer $CULLING_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"eventDir":"text"}'

Responses

  • 200 — Started: the year's best go into <event>_best/ with best.json
  • 400 — Already running

GET /api/cloud/google-drive/account

Google Drive account

curl -X GET http://127.0.0.1:9100/api/cloud/google-drive/account \
  -H "Authorization: Bearer $CULLING_API_TOKEN"

Responses

  • 200 — The Google account deliveries use (never the tokens)

DELETE /api/cloud/google-drive/account

Sign out of Google Drive

curl -X DELETE http://127.0.0.1:9100/api/cloud/google-drive/account \
  -H "Authorization: Bearer $CULLING_API_TOKEN"

Responses

  • 200 — Sign out: forget the refresh token

POST /api/cloud/google-drive/sign-in

Sign in to Google Drive

Body

FieldTypeRequiredDescription
clientIdstringOAuth client ID of a **Desktop app** client (Google Cloud Console → Credentials). Omit to reuse the one this machine signed in with, or `CULLING_GOOGLE_CLIENT_ID` from the environment.
clientSecretstringClient secret for that client. Omit to reuse the stored one, or `CULLING_GOOGLE_CLIENT_SECRET`.
scopestringDefaults to per-file access (`.../auth/drive.file`). Pass `https://www.googleapis.com/auth/drive` when delivering into a folder this app did not create and the per-file scope is refused.
curl -X POST http://127.0.0.1:9100/api/cloud/google-drive/sign-in \
  -H "Authorization: Bearer $CULLING_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"clientId":"text","clientSecret":"text","scope":"text"}'

Responses

  • 200 — Consent page opened; call sign-in/finish to wait for it
  • 400 — No OAuth client to sign in with

POST /api/cloud/google-drive/sign-in/finish

Finish Google Drive sign-in

Body

FieldTypeRequiredDescription
timeoutSecsnumberSeconds to wait for the browser. Defaults to 300.
curl -X POST http://127.0.0.1:9100/api/cloud/google-drive/sign-in/finish \
  -H "Authorization: Bearer $CULLING_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"timeoutSecs":0}'

Responses

  • 200 — Signed in; the refresh token is in the keychain
  • 400 — No sign-in in progress, or Google refused
  • 408 — The browser never came back

GET /api/connections

Connections

curl -X GET http://127.0.0.1:9100/api/connections \
  -H "Authorization: Bearer $CULLING_API_TOKEN"

Responses

  • 200 — Connection profiles with secrets redacted; secrets_set names the stored write-only credentials

PUT /api/connections/{name}

Save connection

ParameterInTypeDescription
namepathstring
curl -X PUT http://127.0.0.1:9100/api/connections/<name> \
  -H "Authorization: Bearer $CULLING_API_TOKEN"

Responses

  • 200 — Create or update a connection profile (secrets write-only)
  • 403 — api_allow_credential_writes is disabled

DELETE /api/connections/{name}

Delete connection

ParameterInTypeDescription
namepathstring
curl -X DELETE http://127.0.0.1:9100/api/connections/<name> \
  -H "Authorization: Bearer $CULLING_API_TOKEN"

Responses

  • 200 — Delete a connection profile and its keychain credentials
  • 403 — api_allow_credential_writes is disabled

POST /api/delivery-report

Delivery report

Body

FieldTypeRequiredDescription
rostersstring[]The start lists' folders, for classes and Identify's journal; every Identify step's when left out.
curl -X POST http://127.0.0.1:9100/api/delivery-report \
  -H "Authorization: Bearer $CULLING_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"rosters":["text"]}'

Responses

  • 200 — The counts and the summary; delivery-report.txt and the captioned delivery-report.pdf are written beside the pictures
  • 400 — No folder is open, or the files could not be written

POST /api/denoise/cancel

Cancel denoise

curl -X POST http://127.0.0.1:9100/api/denoise/cancel \
  -H "Authorization: Bearer $CULLING_API_TOKEN"

Responses

  • 200 — Denoise batch cancelled

POST /api/denoise/flush

Denoise now

curl -X POST http://127.0.0.1:9100/api/denoise/flush \
  -H "Authorization: Bearer $CULLING_API_TOKEN"

Responses

  • 200 — Denoise queue flushed
  • 400 — No active profile or empty queue

GET /api/denoise/profiles

Denoise profiles

curl -X GET http://127.0.0.1:9100/api/denoise/profiles \
  -H "Authorization: Bearer $CULLING_API_TOKEN"

Responses

  • 200 — List of denoise profiles

POST /api/denoise/profiles

Save denoise profile

curl -X POST http://127.0.0.1:9100/api/denoise/profiles \
  -H "Authorization: Bearer $CULLING_API_TOKEN"

Responses

  • 200 — Saved
  • 400 — No name, an unknown field or a value of the wrong type

DELETE /api/denoise/profiles/{name}

Delete denoise profile

ParameterInTypeDescription
namepathstringThe profile's name
curl -X DELETE http://127.0.0.1:9100/api/denoise/profiles/<name> \
  -H "Authorization: Bearer $CULLING_API_TOKEN"

Responses

  • 200 — Deleted; none is active if it was
  • 404 — None by that name

POST /api/denoise/profiles/{name}/test

Test denoise profile

ParameterInTypeDescription
namepathstringThe profile's name
curl -X POST http://127.0.0.1:9100/api/denoise/profiles/<name>/test \
  -H "Authorization: Bearer $CULLING_API_TOKEN"

Responses

  • 200 — The program is there and answers, as Test Program says
  • 400 — It is not, and why
  • 404 — None by that name

PUT /api/denoise/profiles/active

Denoise profile

Body

FieldTypeRequiredDescription
namestringyesName of the profile to activate
curl -X PUT http://127.0.0.1:9100/api/denoise/profiles/active \
  -H "Authorization: Bearer $CULLING_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"name":"text"}'

Responses

  • 200 — Active profile updated
  • 404 — Profile not found

GET /api/denoise/profiles/setups

Denoise profiles as stored

curl -X GET http://127.0.0.1:9100/api/denoise/profiles/setups \
  -H "Authorization: Bearer $CULLING_API_TOKEN"

Responses

  • 200 — Every denoise profile as stored, with every field, and the active one

GET /api/denoise/queue

Denoise queue

curl -X GET http://127.0.0.1:9100/api/denoise/queue \
  -H "Authorization: Bearer $CULLING_API_TOKEN"

Responses

  • 200 — Denoise queue status

DELETE /api/denoise/queue/{index}

Remove from denoise queue

ParameterInTypeDescription
indexpathnumberQueue item index
curl -X DELETE http://127.0.0.1:9100/api/denoise/queue/<index> \
  -H "Authorization: Bearer $CULLING_API_TOKEN"

Responses

  • 200 — Item removed from queue
  • 400 — Invalid index

POST /api/denoise/send

Send to denoise

curl -X POST http://127.0.0.1:9100/api/denoise/send \
  -H "Authorization: Bearer $CULLING_API_TOKEN"

Responses

  • 200 — Images sent to the denoise program, or queued for the next batch
  • 400 — No images loaded, no profile configured, or the launch failed

GET /api/denoise/settings

Denoise settings

curl -X GET http://127.0.0.1:9100/api/denoise/settings \
  -H "Authorization: Bearer $CULLING_API_TOKEN"

Responses

  • 200 — Denoise settings

PUT /api/denoise/settings

Change denoise settings

Body

FieldTypeRequiredDescription
auto_denoise_min_ratingnumberAuto-denoise a picture rated at least this many stars; 0 is off.
auto_denoise_on_pickbooleanEnable/disable auto-denoise when an image is flagged as Pick
curl -X PUT http://127.0.0.1:9100/api/denoise/settings \
  -H "Authorization: Bearer $CULLING_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"auto_denoise_min_rating":0,"auto_denoise_on_pick":true}'

Responses

  • 200 — Settings updated

POST /api/event-site

Build race gallery

Body

FieldTypeRequiredDescription
deliveredstring[]The delivered pictures; the event's delivered/ folders when left out.
eventDirstringyesA path. In an instance started with `--dir` it is in the instance's root: `/` is the root, and a path that leads out of it is refused (403).
localFlagbooleanFlag riders from Jærbladet's clubs and places.
photographerByFolderbooleanCredit by the folder under in/ rather than the file name.
sharpestFirstbooleanEach runner's pictures listed sharpest-on-them first (#810).
siteDirstringyesA path. In an instance started with `--dir` it is in the instance's root: `/` is the root, and a path that leads out of it is refused (403).
slugstringThe event's name in the site; the event folder's name when left out.
smugmugAlbumstring
smugmugConnectionstringA SmugMug connection and the album the pictures are hosted in (link, node id or path); without them, sizes are written beside the manifest.
softRunnerSharenumberA runner read less than this share of the sharpest person in a picture of several loses their number there, and the picture is not in their gallery (#810). Left out, every delivered number is listed.
curl -X POST http://127.0.0.1:9100/api/event-site \
  -H "Authorization: Bearer $CULLING_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"eventDir":"text","siteDir":"text"}'

Responses

  • 200 — The gallery's manifest.json is written
  • 400 — No start list or pictures, a number no start-list entry has, or SmugMug said no

GET /api/eventphotos/events

eventphotos events

ParameterInTypeDescription
connectionquerystringThe eventphotos connection profile, by name.
curl -X GET http://127.0.0.1:9100/api/eventphotos/events \
  -H "Authorization: Bearer $CULLING_API_TOKEN"

Responses

  • 200 — Events the connection's token can publish to
  • 400 — No such connection, bad token, or eventphotos unreachable

POST /api/gallery/add

Add to gallery

Body

FieldTypeRequiredDescription
connectionstringThe gallery connection; left out, the one with an album, else the first.
pathsstring[]yes
curl -X POST http://127.0.0.1:9100/api/gallery/add \
  -H "Authorization: Bearer $CULLING_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"paths":["text"]}'

Responses

  • 200 — In the gallery's album; it sends them by itself
  • 400 — No gallery connection, or the album could not be saved

POST /api/gallery/artwork/preset

Apply gallery preset

Body

FieldTypeRequiredDescription
pathstringyesA path. In an instance started with `--dir` it is in the instance's root: `/` is the root, and a path that leads out of it is refused (403).
presetIdnumberyes
curl -X POST http://127.0.0.1:9100/api/gallery/artwork/preset \
  -H "Authorization: Bearer $CULLING_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"path":"text","presetId":0}'

Responses

  • 200 — The preset's sizes and prices on the artwork (those the picture is too small for left out)
  • 400 — Not in a gallery, or no such preset

POST /api/gallery/bulk

Gallery status or preset for many

Body

FieldTypeRequiredDescription
pathsstring[]yes
presetIdnumber
statusstring`draft`, `published` or `hidden`.
curl -X POST http://127.0.0.1:9100/api/gallery/bulk \
  -H "Authorization: Bearer $CULLING_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"paths":["text"]}'

Responses

  • 200 — Changed; pictures not in a gallery are skipped
  • 400 — Not a status, or the gallery refused

GET /api/library/corrections

Corrections

curl -X GET http://127.0.0.1:9100/api/library/corrections \
  -H "Authorization: Bearer $CULLING_API_TOKEN"

Responses

  • 200 — The corrections made to what workflows delivered, newest first: the picture, what the workflow did, what it was corrected to, why, and who

DELETE /api/library/corrections

Remove every correction

curl -X DELETE http://127.0.0.1:9100/api/library/corrections \
  -H "Authorization: Bearer $CULLING_API_TOKEN"

Responses

  • 200 — Every correction removed, and what was learnt from them

DELETE /api/library/corrections/{id}

Remove a correction

ParameterInTypeDescription
idpathnumberThe correction's id
curl -X DELETE http://127.0.0.1:9100/api/library/corrections/<id> \
  -H "Authorization: Bearer $CULLING_API_TOKEN"

Responses

  • 200 — Removed, and what was learnt from it: a crop's example, an exposure's part in its shape
  • 404 — No such correction

POST /api/pick-for-delivery

Pick for delivery

Body

FieldTypeRequiredDescription
countnumberyesAt most this many pictures.
label"red" | "yellow" | "green" | "blue" | "purple" | "orange" | "pink" | "gray"The color label: red, yellow, green, blue, purple, orange, pink, gray
curl -X POST http://127.0.0.1:9100/api/pick-for-delivery \
  -H "Authorization: Bearer $CULLING_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"count":0}'

Responses

  • 200 — What was picked and why, who got no picture; the picks have the label and an album
  • 400 — No folder is open

GET /api/publish/albums

Published albums

curl -X GET http://127.0.0.1:9100/api/publish/albums \
  -H "Authorization: Bearer $CULLING_API_TOKEN"

Responses

  • 200 — Every album bound to a destination, with the state of each picture there and what the destination holds besides

GET /api/publish/albums/{name}

Published album

ParameterInTypeDescription
namepathstringAlbum (manual collection) name
curl -X GET http://127.0.0.1:9100/api/publish/albums/<name> \
  -H "Authorization: Bearer $CULLING_API_TOKEN"

Responses

  • 200 — The album, with the state of each picture and the sync running or last run
  • 400 — No such album

PUT /api/publish/albums/{name}/binding

Publish album to

ParameterInTypeDescription
namepathstringAlbum name; created when it does not exist

Body

FieldTypeRequiredDescription
autoSyncbooleanKept in sync by itself (the default), or only when asked.
connectionstringyesThe connection profile that reaches the destination, by name.
eventIdnumberThe eventphotos event, for `eventphotos`.
exportProfilestringFor `files`: the export profile each picture is sent as; left out, the original.
kind"eventphotos" | "files" | "smugmug" | "gallery" | "flickr"yesWhat kind of place an album is published to (#753). An album bound before #753 has no kind written and is an eventphotos event.
placestringThe folder under the connection's, for `files` (empty is the connection's own); the gallery for `smugmug`: its link, node id, or a folder path ending in its name; the set for `flickr`: its id or title.
softRunnerSharenumberFor `eventphotos` (#810): a runner read less than this share of the sharpest person in a picture of several is not tagged with their number there. Left out, every number is tagged.
textsany
curl -X PUT http://127.0.0.1:9100/api/publish/albums/<name>/binding \
  -H "Authorization: Bearer $CULLING_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"kind":"eventphotos","connection":"text"}'

Responses

  • 200 — The album is bound. Binding it to another place starts it over there; what was sent to the old one stays
  • 400 — Unknown connection, or a place the connection cannot reach

DELETE /api/publish/albums/{name}/binding

Stop publishing album

ParameterInTypeDescription
namepathstringAlbum name
curl -X DELETE http://127.0.0.1:9100/api/publish/albums/<name>/binding \
  -H "Authorization: Bearer $CULLING_API_TOKEN"

Responses

  • 200 — The album no longer syncs; what is out there stays
  • 400 — The albums could not be saved

POST /api/publish/albums/{name}/items

Change published album pictures

ParameterInTypeDescription
namepathstringAlbum name

Body

FieldTypeRequiredDescription
addstring[]Absolute paths to add to the album.
removestring[]Absolute paths to take out; what was sent is taken down at the next sync.
curl -X POST http://127.0.0.1:9100/api/publish/albums/<name>/items \
  -H "Authorization: Bearer $CULLING_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"add":["text"],"remove":["text"]}'

Responses

  • 200 — How many pictures went in and out
  • 400 — No such album

DELETE /api/publish/albums/{name}/outside/{id}

Remove item not from photosuite

ParameterInTypeDescription
namepathstringAlbum name
idpathstringThe item's id at the destination, from the album's `outside`
curl -X DELETE http://127.0.0.1:9100/api/publish/albums/<name>/outside/<id> \
  -H "Authorization: Bearer $CULLING_API_TOKEN"

Responses

  • 200 — Taken down at the destination
  • 400 — Not one of the album's outside items (what the album sent comes down by taking it out of the album), or the destination refused

POST /api/publish/albums/{name}/outside/{id}/link

Link item to picture

ParameterInTypeDescription
namepathstringAlbum name
idpathstringThe item's id at the destination, from the album's `outside`

Body

FieldTypeRequiredDescription
pathstringyesA path. In an instance started with `--dir` it is in the instance's root: `/` is the root, and a path that leads out of it is refused (403).
curl -X POST http://127.0.0.1:9100/api/publish/albums/<name>/outside/<id>/link \
  -H "Authorization: Bearer $CULLING_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"path":"text"}'

Responses

  • 200 — The picture is in the album as that item; the next sync sends it over it
  • 400 — Not one of the album's outside items, no such picture, or the picture is already published there

POST /api/publish/albums/{name}/sync

Sync published album now

ParameterInTypeDescription
namepathstringAlbum name
curl -X POST http://127.0.0.1:9100/api/publish/albums/<name>/sync \
  -H "Authorization: Bearer $CULLING_API_TOKEN"

Responses

  • 200 — Syncing in the background; follow it on GET /api/publish/albums/{name}
  • 400 — Not bound, or already syncing

GET /api/published/by-photographer

Published by photographer

curl -X GET http://127.0.0.1:9100/api/published/by-photographer \
  -H "Authorization: Bearer $CULLING_API_TOKEN"

Responses

  • 200 — Per photographer and event: delivered, published, which files; and the same as CSV

POST /api/published/import

Import published

Body

FieldTypeRequiredDescription
liststringyesThe editor's list: `published.json` (`[{file, caption}]`) or one file name per line.
curl -X POST http://127.0.0.1:9100/api/published/import \
  -H "Authorization: Bearer $CULLING_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"list":"text"}'

Responses

  • 200 — Which of the open folder's pictures the editor published, recorded and in an album; the taste learned once there is enough
  • 400 — No folder is open, or the list names none of its pictures

POST /api/start-lists/fetch

Fetch start list

Body

FieldTypeRequiredDescription
dirany
exclude_contestsstring[]Contests not on the course, by part of their name (`Tilskuer`: a spectator ticket with a number). Remembered in the folder; omitted, the folder's own are kept.
heat_numbersbooleanA relay of teams whose numbers carry the heat, `07-422` (Energistafetten): race-result only.
resultsbooleanAlso fetch the event's results (race-result): place and time per number, for captions. A folder that has them gets them again anyway.
sourcestringThe start list's page (race-result, elapse.no, racetracker.no, onreg) or a CSV file. Empty: fetch `dir`'s start list again.
curl -X POST http://127.0.0.1:9100/api/start-lists/fetch \
  -H "Authorization: Bearer $CULLING_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"dir":null,"exclude_contests":["text"],"heat_numbers":true}'

Responses

  • 200 — The start list is in the folder; put the folder in an Identify step's rosters
  • 400 — Not a start list, not reachable, or nobody on it with a number; the folder is left as it was

GET /api/tether/config

Tether settings

curl -X GET http://127.0.0.1:9100/api/tether/config \
  -H "Authorization: Bearer $CULLING_API_TOKEN"

Responses

  • 200 — FTP tether config with the password redacted (password_set flags a stored one)

PATCH /api/tether/config

Change tether settings

curl -X PATCH http://127.0.0.1:9100/api/tether/config \
  -H "Authorization: Bearer $CULLING_API_TOKEN"

Responses

  • 200 — Deep-merge the patch into the tether config; a password field is write-only
  • 403 — Patch carries a password but api_allow_credential_writes is disabled

POST /api/tether/start

Start tether

curl -X POST http://127.0.0.1:9100/api/tether/start \
  -H "Authorization: Bearer $CULLING_API_TOKEN"

Responses

  • 200 — The server is starting with the tether setup; `connect_addresses` fill in when it listens
  • 400 — It runs already, or could not start

GET /api/tether/status

Tether status

curl -X GET http://127.0.0.1:9100/api/tether/status \
  -H "Authorization: Bearer $CULLING_API_TOKEN"

Responses

  • 200 — Whether the FTP tether server runs, where a camera connects, and what has arrived

POST /api/tether/stop

Stop tether

curl -X POST http://127.0.0.1:9100/api/tether/stop \
  -H "Authorization: Bearer $CULLING_API_TOKEN"

Responses

  • 200 — The server is stopped

POST /api/upload

Queue for upload

Body

FieldTypeRequiredDescription
indicesnumber[]Image indices to queue for upload. If empty/absent, current image is used.
curl -X POST http://127.0.0.1:9100/api/upload \
  -H "Authorization: Bearer $CULLING_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"indices":[0]}'

Responses

  • 200 — Images queued for upload
  • 400 — Invalid indices

GET /api/upload/destinations

Upload destinations

curl -X GET http://127.0.0.1:9100/api/upload/destinations \
  -H "Authorization: Bearer $CULLING_API_TOKEN"

Responses

  • 200 — List upload destinations

POST /api/upload/destinations

Add upload destination

Body

FieldTypeRequiredDescription
connectionstringName of a connection (Settings → Connections) that files can be written to. Required when adding.
remote_pathstringFolder on the connection; template variables such as `{date}` are filled in when a file is sent. Empty means the connection's own.
curl -X POST http://127.0.0.1:9100/api/upload/destinations \
  -H "Authorization: Bearer $CULLING_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"connection":"text","remote_path":"text"}'

Responses

  • 200 — Destination added; the new list
  • 400 — No such connection, or not one files can be written to

PUT /api/upload/destinations/{index}

Change upload destination

ParameterInTypeDescription
indexpathnumberDestination index, as listed

Body

FieldTypeRequiredDescription
connectionstringName of a connection (Settings → Connections) that files can be written to. Required when adding.
remote_pathstringFolder on the connection; template variables such as `{date}` are filled in when a file is sent. Empty means the connection's own.
curl -X PUT http://127.0.0.1:9100/api/upload/destinations/<index> \
  -H "Authorization: Bearer $CULLING_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"connection":"text","remote_path":"text"}'

Responses

  • 200 — Destination changed; the new list
  • 400 — No such connection, or not one files can be written to
  • 404 — No destination at that index

DELETE /api/upload/destinations/{index}

Delete upload destination

ParameterInTypeDescription
indexpathnumberDestination index, as listed
curl -X DELETE http://127.0.0.1:9100/api/upload/destinations/<index> \
  -H "Authorization: Bearer $CULLING_API_TOKEN"

Responses

  • 200 — Destination removed with what was queued for it; the new list
  • 404 — No destination at that index

POST /api/upload/destinations/{index}/flush

Upload to destination

ParameterInTypeDescription
indexpathnumberThe destination's place in GET /api/upload/destinations
curl -X POST http://127.0.0.1:9100/api/upload/destinations/<index>/flush \
  -H "Authorization: Bearer $CULLING_API_TOKEN"

Responses

  • 200 — What is queued for that destination is being sent
  • 400 — Its connection does not exist
  • 404 — No such destination

POST /api/upload/flush

Process upload queue

curl -X POST http://127.0.0.1:9100/api/upload/flush \
  -H "Authorization: Bearer $CULLING_API_TOKEN"

Responses

  • 200 — Flush upload queue

GET /api/upload/queue

Upload queue

curl -X GET http://127.0.0.1:9100/api/upload/queue \
  -H "Authorization: Bearer $CULLING_API_TOKEN"

Responses

  • 200 — Upload queue status

DELETE /api/upload/queue/{index}

Remove from upload queue

ParameterInTypeDescription
indexpathnumberThe item's place in GET /api/upload/queue
curl -X DELETE http://127.0.0.1:9100/api/upload/queue/<index> \
  -H "Authorization: Bearer $CULLING_API_TOKEN"

Responses

  • 200 — Taken off the queue
  • 404 — No such item
  • 409 — It is being sent, or was sent

POST /api/upload/queue/clear-completed

Clear completed uploads

curl -X POST http://127.0.0.1:9100/api/upload/queue/clear-completed \
  -H "Authorization: Bearer $CULLING_API_TOKEN"

Responses

  • 200 — The sent files are off the list (Clear Completed)

POST /api/upload/queue/retry-failed

Retry failed uploads

curl -X POST http://127.0.0.1:9100/api/upload/queue/retry-failed \
  -H "Authorization: Bearer $CULLING_API_TOKEN"

Responses

  • 200 — Every failed file queued again (Retry Failed)

GET /api/upload/settings

Upload settings

curl -X GET http://127.0.0.1:9100/api/upload/settings \
  -H "Authorization: Bearer $CULLING_API_TOKEN"

Responses

  • 200 — How uploads are sent: RAW+JPEG, IPTC on upload, a saved copy

PATCH /api/upload/settings

Change upload settings

curl -X PATCH http://127.0.0.1:9100/api/upload/settings \
  -H "Authorization: Bearer $CULLING_API_TOKEN"

Responses

  • 200 — The upload settings as they are now
  • 400 — An unknown field or a value of the wrong type

POST /api/upload/transferred/clear

Clear transferred marks

curl -X POST http://127.0.0.1:9100/api/upload/transferred/clear \
  -H "Authorization: Bearer $CULLING_API_TOKEN"

Responses

  • 200 — Which pictures were sent where is forgotten (Clear Transferred); a filter on it shows everything

GET /api/watch

Workflow watcher

curl -X GET http://127.0.0.1:9100/api/watch \
  -H "Authorization: Bearer $CULLING_API_TOKEN"

Responses

  • 200 — The watcher's settings, what it has found about the running workflow, and what Claude costs

PUT /api/watch

Set the workflow watcher

Body

FieldTypeRequiredDescription
claude_every_minutesnumber0 asks only the rules.
enabledboolean
idle_minutesnumber
min_free_gbnumber
modelstring
notifyboolean
picturesbooleanShow Claude the pictures delivered since the last check (#913).
queue_minutesnumber
curl -X PUT http://127.0.0.1:9100/api/watch \
  -H "Authorization: Bearer $CULLING_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"claude_every_minutes":0,"enabled":true,"idle_minutes":0}'

Responses

  • 200 — The watcher as it is now
  • 400 — A field the watcher does not have

GET /api/workflow/files

What the workflow did to each picture

ParameterInTypeDescription
sincequerynumberThe last id seen: only pictures finished after it (default 0, all kept). One past the last id there is (the app started again) is 0.
limitquerynumberHow many at most (default 100, at most 1000).
curl -X GET http://127.0.0.1:9100/api/workflow/files \
  -H "Authorization: Bearer $CULLING_API_TOKEN"

Responses

  • 200 — The records of the pictures a workflow finished after `since`, oldest first: each step's outcome, what went out and where, how long it took, and the first failure

GET /api/workflow/files/{id}

What the workflow did to one picture

ParameterInTypeDescription
idpathnumberThe record's id
curl -X GET http://127.0.0.1:9100/api/workflow/files/<id> \
  -H "Authorization: Bearer $CULLING_API_TOKEN"

Responses

  • 200 — The picture's record
  • 404 — No such record: never made, or older than the records kept

POST /api/workflow/files/{id}/hold

Hold a picture back

ParameterInTypeDescription
idpathnumberThe record's id

Body

FieldTypeRequiredDescription
by"photographer" | "api" | "claude"The holder: photographer, api, claude
reasonstringyesWhy it is kept back, for whoever looks at the held pictures.
curl -X POST http://127.0.0.1:9100/api/workflow/files/<id>/hold \
  -H "Authorization: Bearer $CULLING_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"reason":"text"}'

Responses

  • 200 — Held: moved out of the retry queue or a local delivery folder into the work folder's held/, taken out of its albums (hidden where published), and `taken` says what is already at a remote destination
  • 404 — No such record
  • 409 — Already held

GET /api/workflow/files/{id}/picture

The picture a workflow delivered

ParameterInTypeDescription
idpathnumberThe record's id
stagequery"delivered" | "source"
long_edgequerynumberThe long edge in pixels (default 1568, what a model reads a picture at; at most 4096).
curl -X GET http://127.0.0.1:9100/api/workflow/files/<id>/picture \
  -H "Authorization: Bearer $CULLING_API_TOKEN"

Responses

  • 200 — The picture as a JPEG, upright, in sRGB
  • 400 — An unknown stage
  • 404 — No such record, nothing went out for it, or its file is no longer on this machine

POST /api/workflow/files/{id}/release

Release a held picture

ParameterInTypeDescription
idpathnumberThe record's id
curl -X POST http://127.0.0.1:9100/api/workflow/files/<id>/release \
  -H "Authorization: Bearer $CULLING_API_TOKEN"

Responses

  • 200 — Released: what holding it took is put back, and it goes where it was going
  • 404 — No such record
  • 409 — Not held

POST /api/workflow/files/{id}/rerun

Run one picture again

ParameterInTypeDescription
idpathnumberThe record's id
curl -X POST http://127.0.0.1:9100/api/workflow/files/<id>/rerun \
  -H "Authorization: Bearer $CULLING_API_TOKEN"

Responses

  • 202 — Queued before any new picture; its record comes as `workflow_file_completed` with `rerun_of`. Says, per destination, whether the new picture replaces the first
  • 404 — No such record, or the picture that arrived is gone
  • 409 — Its workflow is not running

GET /api/workflow/files/sheet

Contact sheet of the last deliveries

ParameterInTypeDescription
nquerynumberHow many of the last delivered pictures (default 16, at most 64).
sincequerynumberOnly pictures finished after this record id (default 0).
curl -X GET http://127.0.0.1:9100/api/workflow/files/sheet \
  -H "Authorization: Bearer $CULLING_API_TOKEN"

Responses

  • 200 — One JPEG, 1544 px wide: the last delivered pictures four to a row, each with its record id and file name under it
  • 404 — No delivered picture after `since` is on this machine

POST /api/workflow/notes

Note in the run

Body

FieldTypeRequiredDescription
picturenumberThe picture's record the note is about.
textstringyes
curl -X POST http://127.0.0.1:9100/api/workflow/notes \
  -H "Authorization: Bearer $CULLING_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"text":"text"}'

Responses

  • 200 — Written into the latest run's report, at this time
  • 400 — No text
  • 409 — No workflow has run yet

POST /api/workflow/pause

Pause workflow

curl -X POST http://127.0.0.1:9100/api/workflow/pause \
  -H "Authorization: Bearer $CULLING_API_TOKEN"

Responses

  • 200 — Paused: pictures keep arriving and wait in the queue, nothing is processed or delivered until it is resumed; a picture run again still runs
  • 400 — No workflow is running

GET /api/workflow/profiles

Workflows

curl -X GET http://127.0.0.1:9100/api/workflow/profiles \
  -H "Authorization: Bearer $CULLING_API_TOKEN"

Responses

  • 200 — List workflow profiles

POST /api/workflow/profiles

New workflow

curl -X POST http://127.0.0.1:9100/api/workflow/profiles \
  -H "Authorization: Bearer $CULLING_API_TOKEN"

Responses

  • 200 — Create workflow profile from JSON

GET /api/workflow/profiles/{index}

Workflow

ParameterInTypeDescription
indexpathnumberProfile index
curl -X GET http://127.0.0.1:9100/api/workflow/profiles/<index> \
  -H "Authorization: Bearer $CULLING_API_TOKEN"

Responses

  • 200 — Get workflow profile

PATCH /api/workflow/profiles/{index}

Change workflow

ParameterInTypeDescription
indexpathnumberWorkflow profile index
curl -X PATCH http://127.0.0.1:9100/api/workflow/profiles/<index> \
  -H "Authorization: Bearer $CULLING_API_TOKEN"

Responses

  • 200 — Changed; its index stays
  • 400 — An unknown field or a value of the wrong type
  • 404 — No such workflow
  • 409 — It is running

DELETE /api/workflow/profiles/{index}

Delete workflow

ParameterInTypeDescription
indexpathnumberProfile index
curl -X DELETE http://127.0.0.1:9100/api/workflow/profiles/<index> \
  -H "Authorization: Bearer $CULLING_API_TOKEN"

Responses

  • 200 — Delete workflow profile

POST /api/workflow/profiles/{index}/clock-offset

Set camera clock from picture

ParameterInTypeDescription
indexpathnumberWorkflow profile index

Body

FieldTypeRequiredDescription
numberstringyesThe number the picture on screen shows.
curl -X POST http://127.0.0.1:9100/api/workflow/profiles/<index>/clock-offset \
  -H "Authorization: Bearer $CULLING_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"number":"text"}'

Responses

  • 200 — The timing point's camera clock offset, set from the picture on screen and the number it shows, as Settings' Set does
  • 400 — No Identify step with a timing point, no picture, or no time for that number
  • 404 — No such workflow

GET /api/workflow/profiles/{index}/config

Workflow settings

ParameterInTypeDescription
indexpathnumberWorkflow profile index
curl -X GET http://127.0.0.1:9100/api/workflow/profiles/<index>/config \
  -H "Authorization: Bearer $CULLING_API_TOKEN"

Responses

  • 200 — The workflow as stored: every step with every field
  • 404 — No such workflow

GET /api/workflow/profiles/{index}/export

Export workflow

ParameterInTypeDescription
indexpathnumberProfile index
curl -X GET http://127.0.0.1:9100/api/workflow/profiles/<index>/export \
  -H "Authorization: Bearer $CULLING_API_TOKEN"

Responses

  • 200 — The workflow as a .photosuite-workflow file: its steps, and the connections, denoise profiles, IPTC templates and export profiles they name. No password, token or key goes in it, and the work folder is left empty (#842).

POST /api/workflow/profiles/from-template

New workflow from template

Body

FieldTypeRequiredDescription
template_idstringyes
curl -X POST http://127.0.0.1:9100/api/workflow/profiles/from-template \
  -H "Authorization: Bearer $CULLING_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"template_id":"text"}'

Responses

  • 200 — Create workflow profile from template

POST /api/workflow/profiles/import

Import workflow

Body

FieldTypeRequiredDescription
connectionsobject[]The connections its Ingest and Export steps name, without secrets.
denoise_profilesobject[]The denoise profiles its Denoise steps name.
export_profilesobject[]The export profiles its Export steps name, without a destination folder.
iptc_templatesobject[]The IPTC templates its Inject Metadata steps name.
photosuite_workflownumberyesThe file's format (1).
workflowobjectyesThe workflow, its work folder empty.
curl -X POST http://127.0.0.1:9100/api/workflow/profiles/import \
  -H "Authorization: Bearer $CULLING_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"photosuite_workflow":0,"workflow":{}}'

Responses

  • 200 — Added beside what is there: a connection or profile with the same name that is the same thing is used as it is, anything else gets a free name. `needs` says what to fill in before it runs.

POST /api/workflow/resume

Resume workflow

curl -X POST http://127.0.0.1:9100/api/workflow/resume \
  -H "Authorization: Bearer $CULLING_API_TOKEN"

Responses

  • 200 — Resumed: the pictures that waited are processed in the order they arrived
  • 400 — No workflow is running

GET /api/workflow/runs

Workflow runs

curl -X GET http://127.0.0.1:9100/api/workflow/runs \
  -H "Authorization: Bearer $CULLING_API_TOKEN"

Responses

  • 200 — The reports of this session's workflow runs, oldest first: what arrived and went out (per destination), held back, run again and failed, the time from arrival, what was found, and the notes

GET /api/workflow/runs/{id}

One workflow run

ParameterInTypeDescription
idpathnumberThe run's id
curl -X GET http://127.0.0.1:9100/api/workflow/runs/<id> \
  -H "Authorization: Bearer $CULLING_API_TOKEN"

Responses

  • 200 — The run's report
  • 404 — No such run in this session

POST /api/workflow/start

Start workflow

Body

FieldTypeRequiredDescription
indexnumberyes
curl -X POST http://127.0.0.1:9100/api/workflow/start \
  -H "Authorization: Bearer $CULLING_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"index":0}'

Responses

  • 200 — Start workflow
  • 400 — Its files could never arrive: no Ingest or Camera Tether step, an unknown connection, a local folder that does not exist
  • 404 — No workflow profile at that index
  • 409 — A workflow is already running

GET /api/workflow/status

Workflow status

curl -X GET http://127.0.0.1:9100/api/workflow/status \
  -H "Authorization: Bearer $CULLING_API_TOKEN"

Responses

  • 200 — Get workflow status

POST /api/workflow/stop

Stop workflow

curl -X POST http://127.0.0.1:9100/api/workflow/stop \
  -H "Authorization: Bearer $CULLING_API_TOKEN"

Responses

  • 200 — Stop the active workflow

GET /api/workflow/templates

Workflow templates

curl -X GET http://127.0.0.1:9100/api/workflow/templates \
  -H "Authorization: Bearer $CULLING_API_TOKEN"

Responses

  • 200 — List workflow templates

GET /api/workflows/run-on-folder

Event folder delivery

curl -X GET http://127.0.0.1:9100/api/workflows/run-on-folder \
  -H "Authorization: Bearer $CULLING_API_TOKEN"

Responses

  • 200 — How far the folder run has come

POST /api/workflows/run-on-folder

Deliver event folder

Body

FieldTypeRequiredDescription
collectionstringAn album or saved search, by name, instead of a folder (#666): its pictures go through the workflow; `out` is then needed.
folderstringA path. In an instance started with `--dir` it is in the instance's root: `/` is the root, and a path that leads out of it is refused (403).
orgstring"© <photographer> / <org>" for a picture credited from its folder.
outany
photographerstringThe photographer of pictures lying right in `folder`, not in a photographer's own folder; the camera's name wins when it has one.
workersnumberPictures at once (4 when left out).
workflowstringyesThe workflow, by name.
curl -X POST http://127.0.0.1:9100/api/workflows/run-on-folder \
  -H "Authorization: Bearer $CULLING_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"workflow":"text"}'

Responses

  • 200 — Started: every picture under the folder goes through the workflow where it lies
  • 400 — No such workflow or folder, or a run is already going

DELETE /api/workflows/run-on-folder

Stop event folder delivery

curl -X DELETE http://127.0.0.1:9100/api/workflows/run-on-folder \
  -H "Authorization: Bearer $CULLING_API_TOKEN"

Responses

  • 200 — Stops after the pictures being worked on
esc
    ↑↓ naviger↵ åpne