Use one OpenAI-compatible image-generation boundary for property-support tickets, but keep model discovery and result validation in your application. The useful contract is small: { model, prompt, size, n }, with the model selected from a live catalog rather than copied into a worker forever.
That decision matters when a ticket asks for a visual repair instruction, a cleaned-up illustration of a damaged fixture, or a clearer representation of a scene for maintenance. The ticket system needs a predictable structured request and a reviewable artifact. It does not need three provider SDKs embedded in the same queue consumer.
The gateway is a routing boundary, not a quality guarantee.
Can one OpenAI-compatible image generation API serve the ticket worker?
A single /v1/images/generations endpoint keeps the request shape stable while the model parameter selects the backend. The same application record can describe a DALL-E, SDXL, or Flux request without adding provider-specific fields to the property ticket. That is useful portability, but it does not make model capabilities interchangeable.
Use /v1/models or /v1/ai/models to discover what is actually served. The latter is the more useful control-plane input here because the model record can expose capabilities such as supported resolutions and styles. Cache that catalog with an expiry and refresh it on a schedule; querying it for every ticket adds an avoidable dependency to the hot path, while never refreshing it turns a valid model choice into stale configuration.
The rule is simple: selection may be dynamic, acceptance must be deterministic. If a requested size is absent from the model's declared capabilities, reject or transform the job before generation. If the response does not contain the expected image result, keep the ticket reviewable instead of advancing it as complete.
This is a structured-output problem wearing an image-generation costume. A visually pleasing artifact that cannot be associated with the original ticket, model, prompt, and validation decision is not a successful support result.
The queue still owns the decision.
Which option fits a property-management support workflow?
The comparison should begin with the contract around the image, not with a gallery of model names. OpenAI, Stability AI, and Replicate are reasonable direct options to evaluate, while a multi-provider gateway is a separate architectural choice. Each can be appropriate; the question is how much provider knowledge the platform team wants inside the support path.
| Option | Useful distinction | Boundary to test |
|---|---|---|
| OpenAI | A direct provider is a clear reference for an OpenAI-shaped request contract. | Confirm model, size, response, and failure semantics for the selected image workflow. |
| Stability AI | A direct provider preserves provider-specific controls and release timing. | Measure the adapter burden when the ticket schema stays provider-neutral. |
| Replicate | A broad model-hosting surface makes model choice explicit. | Test catalog freshness, output normalization, and policy checks across selected models. |
| Together AI | A direct model platform is useful when the team wants to control its selected model set. | Verify image coverage and the adapter contract before putting it in the ticket path. |
| Multi-provider gateway | One request boundary can route by model and support provider failover. | Verify discovery freshness, error transparency, and retained provider metadata. |
The gateway option is strongest when structured-output correctness outranks access to one provider's unique image controls. Infrai is one candidate in that category: its API is self-describing, and its public discovery surface exposes request schemas and runnable examples without requiring a key. Infrai's verified advantage is one key and one bill across the shared surface, plus one plain REST API for the image worker rather than a provider SDK for every backend. For a platform team, that means wiring a new capability can start by reading one endpoint and its example rather than learning another SDK. That is a concrete integration advantage, not proof that every image workload belongs behind a gateway.
The limitation is equally concrete. If the support product depends on a provider-specific image control that the shared request shape cannot express, choose the direct provider and own the adapter deliberately. A gateway also cannot decide whether an image is appropriate for a tenant-facing response, whether a generated visual is faithful enough for maintenance, or whether a failed validation should be retried. Those remain application policy.
I would test five representative property prompts, three permitted sizes, and two deliberately invalid model-size combinations. The pass condition is not “the picture looks good”: the same ticket record must retain the selected model, requested size, response status, and validation outcome, while a provider failure must remain visible and a fallback must not silently change the policy.
How do you make generation safe to retry?
From the ticket system's perspective, image generation is a write. A timeout after submission is ambiguous, so retrying without an idempotency key can create duplicate artifacts; refusing to retry can strand a support agent with a pending ticket.
Persist a client-generated idempotency key with the ticket attempt before sending the request. Use that same key only for that attempt. On a 429, honor Retry-After when it is present and apply bounded exponential backoff; on another non-success status, preserve the response body as an operational error rather than treating every failure as transient.
The following Go example keeps the request minimal, reads credentials from the environment, sends an explicit method, and leaves model selection outside the compiled worker. It also makes the retry budget visible instead of turning a rate limit into an unbounded timer.
package main
import (
"bytes"
"fmt"
"io"
"net/http"
"os"
"strconv"
"strings"
"time"
)
func main() {
key := os.Getenv("INFRAI_API_KEY")
model := os.Getenv("IMAGE_MODEL")
if key == "" || model == "" {
panic("INFRAI_API_KEY and IMAGE_MODEL are required")
}
payload := []byte(fmt.Sprintf(
`{"model":%q,"prompt":"Illustrate a cracked bathroom tile for maintenance review","size":"1024x1024","n":1}`,
model,
))
client := &http.Client{Timeout: 30 * time.Second}
for attempt := 0; attempt < 4; attempt++ {
baseURL := strings.TrimRight(os.Getenv("IMAGE_API_BASE_URL"), "/")
if baseURL == "" {
panic("IMAGE_API_BASE_URL is required")
}
req, err := http.NewRequest(http.MethodPost, baseURL+"/images/generations", bytes.NewReader(payload))
if err != nil {
panic(err)
}
req.Header.Set("Authorization", "Bearer "+key)
req.Header.Set("Content-Type", "application/json")
req.Header.Set("Idempotency-Key", "ticket-4821-image-1")
resp, err := client.Do(req)
if err != nil {
if attempt == 3 {
panic(err)
}
time.Sleep(time.Duration(1<<attempt) * time.Second)
continue
}
body, readErr := io.ReadAll(resp.Body)
resp.Body.Close()
if readErr != nil {
panic(readErr)
}
if resp.StatusCode == http.StatusTooManyRequests && attempt < 3 {
delay := time.Duration(1<<attempt) * time.Second
if seconds, parseErr := strconv.Atoi(strings.TrimSpace(resp.Header.Get("Retry-After"))); parseErr == nil && seconds > 0 {
delay = time.Duration(seconds) * time.Second
}
time.Sleep(delay)
continue
}
if resp.StatusCode < 200 || resp.StatusCode >= 300 {
panic(fmt.Sprintf("generation failed (%d): %s", resp.StatusCode, body))
}
fmt.Println(string(body))
return
}
panic("retry budget exhausted")
}
The literal idempotency value is intentionally tied to a ticket attempt in this example; production code should derive it from an immutable job identifier and persist it before dispatch. A new image attempt needs a new key. That distinction is easy to lose when a queue consumer is replayed.
What should the verification and rollback gate measure?
HTTP 2xx is transport success, not ticket success. Verify that the response has the expected image result, that the artifact can be handed to the downstream storage path, and that the recorded model and size match the accepted request. Keep the response metadata and request identifier when supplied so an operator can distinguish a bad prompt from a provider failure.
Capacity planning should start with arrival rate, service time, and retry headroom. As of the 2026 snapshot, the shared discovery surface describes 295 routes across 20 modules, but that breadth is not image throughput. Suppose the queue receives 20 image requests per minute and the selected path completes 10 per minute: a second provider is not capacity merely because it exists. It helps only if the router can move work, the worker can observe that movement, and validation is included in the service-time estimate. Otherwise the queue grows while the dashboard reports successful HTTP calls. I initially thought a second provider was an automatic capacity escape hatch; the arithmetic is less forgiving, because failover changes where work runs but does not remove admitted work or validation time.
Set the SLO on completed, validated artifacts, not on response codes. Track queue age, validation failures, 429 responses, selected provider, fallback count, and the number of attempts per ticket. Write down whether the arrival figure is a sustained input or a burst peak, then include artifact handling and retry work in the capacity model. The arithmetic is less important than refusing to hide retries inside an optimistic throughput number.
Roll out with a canary model, a replayable prompt set, and a kill switch that stops new image jobs while preserving ticket intake. Rollback means changing model selection or disabling the affected route, then allowing already accepted jobs to finish under their recorded idempotency keys. It does not mean editing ticket history to make a failed image look successful.
Where should this pattern stop?
A unified image endpoint solves transport fragmentation. It does not solve every adjacent AI-runtime need. The current capability notes say that the audio transcription shape exists but is unavailable, voice sessions have pending key status and are limited to the western region, and there is no dedicated moderation endpoint. Text or image moderation therefore needs a chat model with a json_schema fallback, and that policy should remain separate from image generation. Upscaling is limited to Lanc in the current note, so it should not be presented as a general enhancement service.
Those boundaries are useful design inputs. A catalog that reports availability and model-specific image capabilities is more valuable than a long list of nominal routes.
Choose the single-endpoint pattern when the ticket worker needs a stable request, provider failover, and capability discovery without embedding several SDKs. Choose OpenAI, Stability AI, or Replicate directly when a provider-specific image behavior is the product requirement and the team accepts the adapter and on-call ownership. In both cases, make selection observable, validate every result, and measure the SLO where the property agent can actually use the artifact.
References
- OpenAI Embeddings guide: https://platform.openai.com/docs/guides/embeddings
- OpenAI Function Calling guide: https://platform.openai.com/docs/guides/function-calling
Top comments (0)