Skip to content

docs: add /images/edits and /images/variations endpoint specs - #1278

Merged
jeremyfowers merged 9 commits into
lemonade-sdk:mainfrom
kenvandine:doc_image_edits
Mar 7, 2026
Merged

jeremyfowers merged 9 commits into
lemonade-sdk:mainfrom
kenvandine:doc_image_edits

Conversation

@kenvandine

@kenvandine kenvandine commented Mar 3, 2026 •

Copy link
Copy Markdown
Member

Document the two new image API endpoints added in #1121:

  • POST /api/v1/images/edits: accepts multipart/form-data with a source image and prompt, returns an edited image. Supports model, image, prompt (required), mask, size, n, response_format, steps, cfg_scale, and seed parameters.

  • POST /api/v1/images/variations: accepts multipart/form-data with a source image, returns a variation with no prompt. Supports model, image (required), size, n, and response_format parameters.

Both sections include parameter tables with status badges and example requests using curl and the OpenAI Python client. The endpoint overview list is also updated to include the two new routes.

Server-side changes (in addition to docs):

  • Wire up steps, cfg_scale, and seed form fields in handle_image_edits — these were documented but not previously extracted from the multipart form
  • Validate full string consumption for integer and float form fields (reject inputs like "10abc" that stoi/stof would silently accept), and reject NaN/Inf for cfg_scale
  • Document OpenAI API compatibility fields (user, background, quality, input_fidelity, output_compression) that are accepted but not forwarded to the backend
  • Clarify that prompt in /images/variations is ignored rather than rejected

Document the two new image API endpoints added in lemonade-sdk#1121:

- POST /api/v1/images/edits: accepts multipart/form-data with a source
  image and prompt, returns an edited image. Supports model, image,
  prompt (required), mask, size, n, response_format, steps, cfg_scale,
  and seed parameters.

- POST /api/v1/images/variations: accepts multipart/form-data with a
  source image, returns a variation with no prompt. Supports model,
  image (required), size, n, and response_format parameters.

Both sections include parameter tables with status badges and example
requests using curl and the OpenAI Python client. The endpoint overview
list is also updated to include the two new routes.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds documentation for two newly introduced OpenAI-compatible image endpoints in the Lemonade Server spec, expanding the documented surface area of the server’s image APIs.

Changes:

  • Add /api/v1/images/edits endpoint documentation (multipart form upload + prompt → edited image).
  • Add /api/v1/images/variations endpoint documentation (multipart form upload → variation, no prompt).
  • Update the endpoints overview list to include both routes.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread docs/server/server_spec.md
Comment thread docs/server/server_spec.md Outdated
Comment thread docs/server/server_spec.md
Comment thread docs/server/server_spec.md
Comment thread docs/server/server_spec.md Outdated
kenvandine and others added 3 commits March 3, 2026 15:42
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
…pat params

- Fix handle_image_edits to actually extract steps, cfg_scale, and seed
  from the multipart form so they are forwarded to the sd.cpp backend
- Document n parameter range (1-10) with 400 error behavior for both
  /images/edits and /images/variations
- Add undocumented OpenAI API compatibility fields (user, background,
  quality, input_fidelity, output_compression) to the /images/edits
  parameter table with a note that they are accepted but not forwarded
- Add user field to /images/variations parameter table with same note

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 2 out of 2 changed files in this pull request and generated 4 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/cpp/server/server.cpp
Comment thread src/cpp/server/server.cpp
Comment thread docs/server/server_spec.md Outdated
Comment thread src/cpp/server/server.cpp
- Use pos overload of stoi/stof to reject inputs with trailing non-numeric
  characters (e.g. "10abc"), which stoi/stof would otherwise silently accept
- Reject NaN and Inf values for cfg_scale
- Update /images/variations note: prompt is not supported and will be
  ignored (the handler never extracted it, so "not accepted" was misleading)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@jeremyfowers
jeremyfowers requested review from meghsat March 3, 2026 21:49
- Log backend error details at ERROR level when image_edits or
  image_variations returns an error response, so the cause is visible
  in server logs instead of just "Error 500"
- Fix api_image_variations example to use SD-Turbo (consistent with
  what the test suite uses and what works reliably) instead of
  Flux-2-Klein-4B, which is an edit model and behaves poorly when
  given the "variation" placeholder prompt via img2img mode
- Explicitly set response_format=b64_json in both example paths
- Wrap the OpenAI client call in try/except to print error details
  instead of crashing silently

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@jeremyfowers jeremyfowers assigned kenvandine and unassigned kenvandine Mar 3, 2026
@jeremyfowers

Copy link
Copy Markdown
Member

@claude review this PR, specifically:

  1. Is the spec accurate with respect to the implementation (which already existed before this PR)?
  2. Are the example requests in the spec likely to work?

@jeremyfowers

Copy link
Copy Markdown
Member

@claude review this PR, specifically:

Is the spec accurate with respect to the implementation (which already existed before this PR)? Are the example requests in the spec likely to work?

lazy robot! lol

@ramkrishna2910

Copy link
Copy Markdown
Contributor

Lol there is a failure in the workflow. I will fix it tonight.

@lemonade-sdk lemonade-sdk deleted a comment from claude Bot Mar 4, 2026
@ramkrishna2910

Copy link
Copy Markdown
Contributor

@claude review this PR, specifically:

Is the spec accurate with respect to the implementation (which already existed before this PR)?
Are the example requests in the spec likely to work?

Comment thread src/cpp/server/server.cpp
@claude

claude Bot commented Mar 4, 2026

Copy link
Copy Markdown

Review Summary

Verdict: APPROVE

Blocking (must fix)

None — no blocking issues found.

Non-blocking (suggestions)

  • [Style] src/cpp/server/server.cpp:2171 — parse_int_field/parse_float_field are local lambdas, but parse_n_from_form (member function) and the output_compression block (line 2157) still use bare std::stoi/std::stoi with no trailing-character validation. Promote the lambdas to member functions and apply the same pos != val.size() guard consistently across all integer/float form parsing. (inline comment)

  • [Nit] docs/server/server_spec.md — The section badge for both new endpoints reads status-fully_available-green, but the parameter tables list n and response_format as partial-yellow. Either downgrade the section badge or update the parameter badges for consistency with the /images/generations section (which does the same thing).

  • [Nit] docs/server/server_spec.md — output_compression is documented as "Accepted but not forwarded to the backend" — this is functionally correct (the SD backend ignores it), but the server does parse and insert it into request_json. Wording like "Accepted; silently ignored by the backend" would be more precise.

  • [Question] docs/server/server_spec.md — The mask parameter for /images/edits is listed as available but it's unclear whether the sd-cpp backend actually supports masked inpainting today. SDServer::image_edits does forward mask_data to sd-server — worth confirming this is tested and works end-to-end before marking it fully available.

Good stuff

  • Solid input validation: the trailing-character check via pos != val.size() and the NaN/Inf guard on cfg_scale are exactly the right approach for untrusted multipart form data.
  • Quad-prefix registration is correctly handled through the existing register_post helper — no new endpoints are missing a prefix.
  • Backend error logging added to image_edits and image_variations is a useful operational improvement.
  • The Python example fix (adding response_format="b64_json" and wrapping the OpenAI client call in try/except) is a clean, practical improvement.
  • Documentation is clear and well-structured, with accurate parameter status badges and working curl/Python examples.

Add pos != val.size() guard to parse_n_from_form and output_compression
parsing, matching the pattern already used in parse_int_field/parse_float_field
lambdas. Update output_compression doc wording for precision.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@kenvandine

Copy link
Copy Markdown
Member Author

Thanks for the thorough review! Addressed the suggestions in 934cc2e:

  1. [Style] Consistent trailing-character validation — Added pos != val.size() guard to both parse_n_from_form and the output_compression block, matching the pattern already used in parse_int_field/parse_float_field lambdas.

  2. [Nit] Badge inconsistency — Left as-is since this matches the existing pattern in /images/generations (section badge is fully_available while n and response_format are partial). All three image endpoints are now consistent.

  3. [Nit] output_compression wording — Updated from "Accepted but not forwarded to the backend" to "Accepted; silently ignored by the backend".

  4. [Question] mask parameter — The sd-cpp backend does support masked inpainting — SDServer::image_edits forwards mask_data to sd-server. Leaving the badge as available.

@jeremyfowers
jeremyfowers merged commit c3d95ef into lemonade-sdk:main Mar 7, 2026
38 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants