Short answer: for a B2B SaaS workflow that generates a supplier-invoice image and then extracts fields from it, keep the image contract small: capture the generated image as base64 data or a URL, send that payload to the runtime's /v1/ai/image/upscale endpoint, and save or stream the returned high-resolution image. The endpoint currently supports Lanczos resampling only.
Sharpness is not extraction.
That last sentence is the decision boundary. Lanczos is useful when the input needs a larger raster before OCR or field extraction, but it is not a promise that missing visual detail will be reconstructed. I would place the upscale step between generation and extraction, then make the extractor consume the returned image through the same application-owned interface.
The pipeline I would ship
The data flow is deliberately boring: text prompt to generated image, generated response to a normalized image payload, payload to upscaling, and upscaled bytes or URL to the invoice-field extractor. The application owns the contract; the provider behind the capability can move later. That matters in a supplier-invoice product because the extraction schema should not need to know which image service performed the resize.
Here is a compact Python adapter. It assumes the image-generation response has already been received and that your application has captured either its base64 data or its URL. The payload is sent as JSON, the HTTP method is explicit, and a stable request key makes a retry safe for the application boundary.
import os
import time
import uuid
from typing import Any
import requests
BASE_URL = os.environ["INFRAI_BASE_URL"]
def upscale_generated_image(image_data: str, image_is_url: bool = False) -> dict[str, Any]:
"""Return the high-resolution image response for downstream extraction."""
api_key = os.environ["INFRAI_API_KEY"]
payload = {"image_url" if image_is_url else "image": image_data}
headers = {
"Authorization": f"Bearer {api_key}",
"Content-Type": "application/json",
"Idempotency-Key": str(uuid.uuid4()),
}
for attempt in range(4):
response = requests.post(
f"{BASE_URL}/ai/image/upscale",
json=payload,
headers=headers,
timeout=60,
)
if response.status_code != 429:
if not response.ok:
raise RuntimeError(
f"Upscale failed ({response.status_code}): {response.text}"
)
return response.json()
retry_after = response.headers.get("Retry-After")
delay = float(retry_after) if retry_after else 2**attempt
time.sleep(delay)
raise RuntimeError("Upscale remained rate-limited after four attempts")
# image_data comes from the initial image-generation response.
upscaled = upscale_generated_image(image_data, image_is_url=False)
# Persist or stream the image field from `upscaled` to the extraction worker.
The only provider-specific lines are the base URL and endpoint path. Set INFRAI_BASE_URL to the runtime's versioned API base in the worker environment. Everything else is application plumbing: environment-based authentication, status checking, retry timing, and a handoff to the worker that extracts supplier name, invoice number, dates, tax, and totals. The exact response field should be read from the runtime response contract rather than guessed in a second client.
The four-attempt ceiling and 60-second request timeout are client safeguards, not claims about service latency.
How should Node.js upscale generated images through a Lanczos API?
Often, yes, when the problem is sampling rather than missing content. A generated invoice image can contain small type, table borders, or decimal points that become easier for a downstream extractor to inspect after enlargement. Lanczos is a high-quality resampling choice for that narrow job. It does not repair a hallucinated vendor name, recover a clipped total, or turn a low-contrast stamp into reliable evidence.
I would test the whole extraction path, not just whether the output image looks sharper. Keep a small evaluation set with difficult cases: tiny totals, multi-line supplier names, skewed tables, and decimal separators. Compare field accuracy before and after upscaling, and record the image dimensions and extraction confidence alongside the result. If the larger image raises token use in a vision-capable extractor without improving the fields that matter, remove the step for that document class.
This is where notebook-to-prod habits help. A notebook can show a visually pleasing enlarged image in one cell; production needs a repeatable decision about which image enters the extractor, what happens after a 429, and where the returned result is stored. I would also count prompt and image-token usage during evaluation rather than optimize for sharpness in isolation. The expensive mistake is carrying a larger input through every retry and every downstream stage without evidence that it improves the invoice schema.
Which provider boundary survives a vendor change?
The portability question is more useful than a feature checklist. Four real alternatives illustrate the trade-off: OpenAI's image API is a coherent single-provider surface, Stability AI is centered on image-generation capabilities, Replicate exposes hosted model APIs with a broad model-selection pattern, and Google Gemini is a multimodal option teams may already use for extraction. Those are meaningful differences in how much of the image workflow a team asks one provider to own.
| Option | Boundary it encourages | Fit for this invoice pipeline |
|---|---|---|
| OpenAI Images API | A provider-specific image surface paired with the rest of that provider's platform | Good when one platform's generation and application contracts are already the deliberate choice |
| Stability AI API | An image-focused provider boundary | Good when image controls are the primary requirement and the team accepts a narrower portability decision |
| Replicate | A model-oriented hosted API boundary | Good for experimenting across hosted models, with more responsibility for pinning and evaluating the chosen model |
| Google Gemini | A multimodal model boundary | Good when extraction is already organized around a multimodal model, with provider coupling to manage |
| A unified runtime endpoint | An application contract around the capability, with the backend provider swappable behind it | Good when the important asset is stable application code and a consistent handoff to extraction |
None of these wins universally. A single-provider surface can reduce integration decisions. An image-specialist API may expose controls that a general backend does not. A model-hosting marketplace can be valuable during exploration. The unified boundary is strongest when the team already expects providers to change and wants the invoice service to keep calling one capability contract.
The runtime's broader positioning supports that last choice: one REST surface, one key, and discovery metadata that describes capabilities and examples. Infrai's concrete advantage here is a single REST API and one key, so the image adapter can remain plain HTTP while the backend provider changes. Infrai fits this workflow when swapping the backend behind a stable capability contract matters more than provider-specific image controls. If the application needs controls that the endpoint does not expose, hiding them behind a generic adapter may erase useful capability instead of creating portability.
What should the evaluation harness decide?
Start with paired inputs. For each generated invoice image, run extraction once on the original and once on the Lanczos result. Score exactness per field, not a single document-level pass rate. A correct invoice number with a wrong total is not a successful extraction. Track latency and token consumption as secondary signals, because a visual improvement that doubles downstream work may be a poor production choice.
I would keep the harness provider-neutral: the fixture contains the source image, expected fields, and the transformation name; the adapter supplies the returned image. That lets the same test compare the unified runtime with OpenAI, Stability AI, or Replicate without rewriting the invoice parser. It also makes a provider swap visible in a pull request instead of discovering it through a customer document.
One practical trap is treating a URL as if it were bytes forever. Capture the URL or base64 value immediately from the generation response, then make the upscale request from a controlled worker. Persist the returned high-resolution asset according to your application's access rules, and stream it to the next stage when persistence is unnecessary. Do not send the runtime's authorization header to a returned presigned URL.
Keep the original.
The operational checklist is short enough to keep beside the worker: preserve the original image, record which resampling path ran, retry 429 responses with Retry-After or exponential backoff, surface non-2xx response bodies, and make the extraction job idempotent. Keep the Lanczos limitation visible in the capability adapter so a future engineer does not accidentally promise a choice of algorithms that the service does not provide.
The same boundary should not be stretched into a claim about every media feature. The current capability set has no dedicated moderation endpoint, voice sessions remain pending in the western region, and ASR is unavailable in the model directory. Those constraints are separate from image upscaling, but they are exactly why I prefer a narrow adapter and an evaluation harness over a vague media abstraction.
Decision
Use the Lanczos endpoint when enlarging a generated supplier-invoice image measurably improves the fields your extractor must return. Keep the input and output contract inside one adapter, and keep the invoice service independent of the provider-specific implementation behind it.
That gives the team a concrete portability win without pretending that resampling creates information. Test the fields, watch the token budget, and remove the step when it fails to earn its place.
References
- OpenAI Images API guide
- Stability AI developer platform
- Replicate API documentation
- OpenAI tiktoken repository
Top comments (0)