# Image picker — agent API Base URL: this server. Every write is JSON, sends `X-Who: ` and, if the server was started with PICKER_TOKEN, `X-Token: `. A product can hold several chosen images (the import CSV takes afbeelding_1..3). `selected` is always the ordered list of candidate ids for that product; the first is the main image. ## Read GET /api/products?filter=todo&q=lenovo&kind=icecat&limit=50&offset=0 -> {stats, count, products:[{external_id, naam, merk, subcategorie, term_en, ean, selected:[id,…], state, candidates:[...]}]} filter: all | todo | done | multi | none | nocand | mfr | rejected GET /api/products/ -> one product with all its candidates GET /api/stats -> progress counters GET /export.csv -> the decisions so far Candidates a human rejected come back with "status":"rejected". Do not re-add them: the same image for the same product is deduped on its URL, and a rejected row stays rejected. Add something different instead. ## Add a candidate POST /api/candidates {"external_id":"42", "kind":"generated", # generated | url | upload "image_url":"https://…" # or "image_b64":"", "filename":"x.png" "label":"SDXL · studio pack shot", "licence":"generated, cleared for own use", "artist":"agent:imagegen", "note":"prompt: white background product photo of …", "ref":"job-1234"} -> {"ok":true, "candidate_id":…, "duplicate":false} An image_url is stored as a link and mirrored locally once somebody selects it. image_b64 also has a home in the UI: the "+ add image" dialog has a "paste base64 (for agents)" section, for agents that can type into a field but cannot drive a file picker. A data: URL prefix and whitespace are both fine. An image_b64 is written into server/media immediately. Anything an agent adds shows up in the UI marked with the agent's name — agents propose, humans choose. ## Decide (only if you were told to) POST /api/select {"external_id":"42","candidate_id":123} # toggles POST /api/select {"external_id":"42","candidate_id":123,"on":true} POST /api/primary {"external_id":"42","candidate_id":123} # make it image 1 POST /api/none {"external_id":"42"} # no usable image exists POST /api/clear {"external_id":"42"} # back to undecided POST /api/pick {"external_id":"42","candidate_id":123} # replaces the whole selection with this one candidate; null = none POST /api/reject {"candidate_id":123,"reason":"wrong model"} POST /api/unreject{"candidate_id":123} Choosing is normally a human act. An agent should add candidates and leave the selection alone unless the operator explicitly asked it to decide.