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
| Field | Type | Required | Description |
|---|---|---|---|
connection | string | A SmugMug connection, for a SmugMug album. | |
folder | string | yes | A 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). |
link | string | yes | A public Flickr album's link, or a SmugMug gallery link or node id. |
originals | boolean | The originals instead of Flickr's largest derived size or SmugMug's 4K. | |
photographer | string | For SmugMug: the folder under `folder` its pictures go into. | |
splitByTitle | boolean | For 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 asked400— 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
| Field | Type | Required | Description |
|---|---|---|---|
count | number | ||
eventDir | string | yes | A 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). |
forgetRejections | boolean | Start the review loop again, forgetting what was deleted. | |
model | string | The local model that looks at the shortlist; none: Vision alone. | |
shortlist | number | Pictures 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.json400— 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
| Field | Type | Required | Description |
|---|---|---|---|
clientId | string | OAuth 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. | |
clientSecret | string | Client secret for that client. Omit to reuse the stored one, or `CULLING_GOOGLE_CLIENT_SECRET`. | |
scope | string | Defaults 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 it400— No OAuth client to sign in with
POST /api/cloud/google-drive/sign-in/finish
Finish Google Drive sign-in
Body
| Field | Type | Required | Description |
|---|---|---|---|
timeoutSecs | number | Seconds 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 keychain400— No sign-in in progress, or Google refused408— 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
| Parameter | In | Type | Description |
|---|---|---|---|
name | path | string |
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
| Parameter | In | Type | Description |
|---|---|---|---|
name | path | string |
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 credentials403— api_allow_credential_writes is disabled
POST /api/delivery-report
Delivery report
Body
| Field | Type | Required | Description |
|---|---|---|---|
rosters | string[] | 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 pictures400— 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 flushed400— 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— Saved400— No name, an unknown field or a value of the wrong type
DELETE /api/denoise/profiles/{name}
Delete denoise profile
| Parameter | In | Type | Description |
|---|---|---|---|
name | path | string | The 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 was404— None by that name
POST /api/denoise/profiles/{name}/test
Test denoise profile
| Parameter | In | Type | Description |
|---|---|---|---|
name | path | string | The 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 says400— It is not, and why404— None by that name
PUT /api/denoise/profiles/active
Denoise profile
Body
| Field | Type | Required | Description |
|---|---|---|---|
name | string | yes | Name 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 updated404— 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
| Parameter | In | Type | Description |
|---|---|---|---|
index | path | number | Queue 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 queue400— 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 batch400— 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
| Field | Type | Required | Description |
|---|---|---|---|
auto_denoise_min_rating | number | Auto-denoise a picture rated at least this many stars; 0 is off. | |
auto_denoise_on_pick | boolean | Enable/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
| Field | Type | Required | Description |
|---|---|---|---|
delivered | string[] | The delivered pictures; the event's delivered/ folders when left out. | |
eventDir | string | yes | A 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). |
localFlag | boolean | Flag riders from Jærbladet's clubs and places. | |
photographerByFolder | boolean | Credit by the folder under in/ rather than the file name. | |
sharpestFirst | boolean | Each runner's pictures listed sharpest-on-them first (#810). | |
siteDir | string | yes | A 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). |
slug | string | The event's name in the site; the event folder's name when left out. | |
smugmugAlbum | string | ||
smugmugConnection | string | A SmugMug connection and the album the pictures are hosted in (link, node id or path); without them, sizes are written beside the manifest. | |
softRunnerShare | number | A 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 written400— No start list or pictures, a number no start-list entry has, or SmugMug said no
GET /api/eventphotos/events
eventphotos events
| Parameter | In | Type | Description |
|---|---|---|---|
connection | query | string | The 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 to400— No such connection, bad token, or eventphotos unreachable
GET /api/gallery
Gallery
| Parameter | In | Type | Description |
|---|---|---|---|
connection | query | string | The gallery connection, by name; left out, the one with an album, else the first. |
curl -X GET http://127.0.0.1:9100/api/gallery \
-H "Authorization: Bearer $CULLING_API_TOKEN"
Responses
200— The gallery, its presets and collections, and the album that is it400— No gallery connection, a refused token, or the gallery unreachable
POST /api/gallery/add
Add to gallery
Body
| Field | Type | Required | Description |
|---|---|---|---|
connection | string | The gallery connection; left out, the one with an album, else the first. | |
paths | string[] | 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 itself400— No gallery connection, or the album could not be saved
GET /api/gallery/artwork
Picture's artwork
| Parameter | In | Type | Description |
|---|---|---|---|
path | query | string | The picture, an absolute path. |
curl -X GET http://127.0.0.1:9100/api/gallery/artwork \
-H "Authorization: Bearer $CULLING_API_TOKEN"
Responses
200— What the gallery shows for the picture, as it is now400— The gallery refused or did not answer
PATCH /api/gallery/artwork
Edit picture in gallery
Body
| Field | Type | Required | Description |
|---|---|---|---|
change | object | yes | The fields to change, as the gallery takes them: status, featured, texts ({lang: {title, description}}), keep ([lang]), variants ([{longEdgeCm, material, label, priceOre}]), editionSize, soldBefore, collections ([id]), awards ([text]). Left out, a field stays. |
path | string | yes | A 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 PATCH http://127.0.0.1:9100/api/gallery/artwork \
-H "Authorization: Bearer $CULLING_API_TOKEN" \
-H "Content-Type: application/json" \
-d '{"path":"text","change":{}}'
Responses
200— The artwork as the gallery has it now400— Not in a gallery, or the gallery refused the change (and why)
POST /api/gallery/artwork/preset
Apply gallery preset
Body
| Field | Type | Required | Description |
|---|---|---|---|
path | string | yes | A 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). |
presetId | number | yes |
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
| Field | Type | Required | Description |
|---|---|---|---|
paths | string[] | yes | |
presetId | number | ||
status | string | `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 skipped400— 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
| Parameter | In | Type | Description |
|---|---|---|---|
id | path | number | The 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 shape404— No such correction
POST /api/pick-for-delivery
Pick for delivery
Body
| Field | Type | Required | Description |
|---|---|---|---|
count | number | yes | At 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 album400— 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
| Parameter | In | Type | Description |
|---|---|---|---|
name | path | string | Album (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 run400— No such album
PUT /api/publish/albums/{name}/binding
Publish album to
| Parameter | In | Type | Description |
|---|---|---|---|
name | path | string | Album name; created when it does not exist |
Body
| Field | Type | Required | Description |
|---|---|---|---|
autoSync | boolean | Kept in sync by itself (the default), or only when asked. | |
connection | string | yes | The connection profile that reaches the destination, by name. |
eventId | number | The eventphotos event, for `eventphotos`. | |
exportProfile | string | For `files`: the export profile each picture is sent as; left out, the original. | |
kind | "eventphotos" | "files" | "smugmug" | "gallery" | "flickr" | yes | What kind of place an album is published to (#753). An album bound before #753 has no kind written and is an eventphotos event. |
place | string | The 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. | |
softRunnerShare | number | For `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. | |
texts | any |
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 stays400— Unknown connection, or a place the connection cannot reach
DELETE /api/publish/albums/{name}/binding
Stop publishing album
| Parameter | In | Type | Description |
|---|---|---|---|
name | path | string | Album 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 stays400— The albums could not be saved
POST /api/publish/albums/{name}/items
Change published album pictures
| Parameter | In | Type | Description |
|---|---|---|---|
name | path | string | Album name |
Body
| Field | Type | Required | Description |
|---|---|---|---|
add | string[] | Absolute paths to add to the album. | |
remove | string[] | 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 out400— No such album
DELETE /api/publish/albums/{name}/outside/{id}
Remove item not from photosuite
| Parameter | In | Type | Description |
|---|---|---|---|
name | path | string | Album name |
id | path | string | The 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 destination400— 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
| Parameter | In | Type | Description |
|---|---|---|---|
name | path | string | Album name |
id | path | string | The item's id at the destination, from the album's `outside` |
Body
| Field | Type | Required | Description |
|---|---|---|---|
path | string | yes | A 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 it400— 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
| Parameter | In | Type | Description |
|---|---|---|---|
name | path | string | Album 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
| Field | Type | Required | Description |
|---|---|---|---|
list | string | yes | The 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 enough400— No folder is open, or the list names none of its pictures
POST /api/start-lists/fetch
Fetch start list
Body
| Field | Type | Required | Description |
|---|---|---|---|
dir | any | ||
exclude_contests | string[] | 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_numbers | boolean | A relay of teams whose numbers carry the heat, `07-422` (Energistafetten): race-result only. | |
results | boolean | Also fetch the event's results (race-result): place and time per number, for captions. A folder that has them gets them again anyway. | |
source | string | The 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 rosters400— 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-only403— 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 listens400— 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
| Field | Type | Required | Description |
|---|---|---|---|
indices | number[] | 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 upload400— 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
| Field | Type | Required | Description |
|---|---|---|---|
connection | string | Name of a connection (Settings → Connections) that files can be written to. Required when adding. | |
remote_path | string | Folder 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 list400— No such connection, or not one files can be written to
PUT /api/upload/destinations/{index}
Change upload destination
| Parameter | In | Type | Description |
|---|---|---|---|
index | path | number | Destination index, as listed |
Body
| Field | Type | Required | Description |
|---|---|---|---|
connection | string | Name of a connection (Settings → Connections) that files can be written to. Required when adding. | |
remote_path | string | Folder 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 list400— No such connection, or not one files can be written to404— No destination at that index
DELETE /api/upload/destinations/{index}
Delete upload destination
| Parameter | In | Type | Description |
|---|---|---|---|
index | path | number | Destination 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 list404— No destination at that index
POST /api/upload/destinations/{index}/flush
Upload to destination
| Parameter | In | Type | Description |
|---|---|---|---|
index | path | number | The 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 sent400— Its connection does not exist404— 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
| Parameter | In | Type | Description |
|---|---|---|---|
index | path | number | The 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 queue404— No such item409— 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 now400— 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
| Field | Type | Required | Description |
|---|---|---|---|
claude_every_minutes | number | 0 asks only the rules. | |
enabled | boolean | ||
idle_minutes | number | ||
min_free_gb | number | ||
model | string | ||
notify | boolean | ||
pictures | boolean | Show Claude the pictures delivered since the last check (#913). | |
queue_minutes | number |
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 now400— A field the watcher does not have
GET /api/workflow/files
What the workflow did to each picture
| Parameter | In | Type | Description |
|---|---|---|---|
since | query | number | The 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. |
limit | query | number | How 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
| Parameter | In | Type | Description |
|---|---|---|---|
id | path | number | The 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 record404— No such record: never made, or older than the records kept
POST /api/workflow/files/{id}/hold
Hold a picture back
| Parameter | In | Type | Description |
|---|---|---|---|
id | path | number | The record's id |
Body
| Field | Type | Required | Description |
|---|---|---|---|
by | "photographer" | "api" | "claude" | The holder: photographer, api, claude | |
reason | string | yes | Why 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 destination404— No such record409— Already held
GET /api/workflow/files/{id}/picture
The picture a workflow delivered
| Parameter | In | Type | Description |
|---|---|---|---|
id | path | number | The record's id |
stage | query | "delivered" | "source" | |
long_edge | query | number | The 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 sRGB400— An unknown stage404— 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
| Parameter | In | Type | Description |
|---|---|---|---|
id | path | number | The 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 going404— No such record409— Not held
POST /api/workflow/files/{id}/rerun
Run one picture again
| Parameter | In | Type | Description |
|---|---|---|---|
id | path | number | The 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 first404— No such record, or the picture that arrived is gone409— Its workflow is not running
GET /api/workflow/files/sheet
Contact sheet of the last deliveries
| Parameter | In | Type | Description |
|---|---|---|---|
n | query | number | How many of the last delivered pictures (default 16, at most 64). |
since | query | number | Only 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 it404— No delivered picture after `since` is on this machine
POST /api/workflow/notes
Note in the run
Body
| Field | Type | Required | Description |
|---|---|---|---|
picture | number | The picture's record the note is about. | |
text | string | yes |
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 time400— No text409— 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 runs400— 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
| Parameter | In | Type | Description |
|---|---|---|---|
index | path | number | Profile 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
| Parameter | In | Type | Description |
|---|---|---|---|
index | path | number | Workflow 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 stays400— An unknown field or a value of the wrong type404— No such workflow409— It is running
DELETE /api/workflow/profiles/{index}
Delete workflow
| Parameter | In | Type | Description |
|---|---|---|---|
index | path | number | Profile 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
| Parameter | In | Type | Description |
|---|---|---|---|
index | path | number | Workflow profile index |
Body
| Field | Type | Required | Description |
|---|---|---|---|
number | string | yes | The 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 does400— No Identify step with a timing point, no picture, or no time for that number404— No such workflow
GET /api/workflow/profiles/{index}/config
Workflow settings
| Parameter | In | Type | Description |
|---|---|---|---|
index | path | number | Workflow 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 field404— No such workflow
GET /api/workflow/profiles/{index}/export
Export workflow
| Parameter | In | Type | Description |
|---|---|---|---|
index | path | number | Profile 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
| Field | Type | Required | Description |
|---|---|---|---|
template_id | string | yes |
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
| Field | Type | Required | Description |
|---|---|---|---|
connections | object[] | The connections its Ingest and Export steps name, without secrets. | |
denoise_profiles | object[] | The denoise profiles its Denoise steps name. | |
export_profiles | object[] | The export profiles its Export steps name, without a destination folder. | |
iptc_templates | object[] | The IPTC templates its Inject Metadata steps name. | |
photosuite_workflow | number | yes | The file's format (1). |
workflow | object | yes | The 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 arrived400— 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
| Parameter | In | Type | Description |
|---|---|---|---|
id | path | number | The 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 report404— No such run in this session
POST /api/workflow/start
Start workflow
Body
| Field | Type | Required | Description |
|---|---|---|---|
index | number | yes |
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 workflow400— Its files could never arrive: no Ingest or Camera Tether step, an unknown connection, a local folder that does not exist404— No workflow profile at that index409— 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
| Field | Type | Required | Description |
|---|---|---|---|
collection | string | An album or saved search, by name, instead of a folder (#666): its pictures go through the workflow; `out` is then needed. | |
folder | string | A 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). | |
org | string | "© <photographer> / <org>" for a picture credited from its folder. | |
out | any | ||
photographer | string | The photographer of pictures lying right in `folder`, not in a photographer's own folder; the camera's name wins when it has one. | |
workers | number | Pictures at once (4 when left out). | |
workflow | string | yes | The 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 lies400— 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