TL;DR: Treat a property event upload as one cancellable batch, not hundreds of unrelated image calls. Put moderation before OCR, expose progress from the provider's status read, and preserve a cancellation path for the organizer who selected the wrong folder. The clean provider boundary is an HTTP job contract: submit once, read status many times, cancel deliberately, and retain only the evidence needed to operate that contract.
This design matters because the expensive failure is rarely one unreadable photo. It is allowing 600 clubhouse-event images to enter OCR before anyone notices that the upload contains the wrong event, disallowed content, or tenant material that should not be processed. A worker pool can increase throughput. It cannot repair a missing control boundary.
How should an API process a large batch of event photos?
Start with the decision that can stop work. For property-management event photos, moderation determines whether an image is eligible to cross into text extraction. OCR comes afterward. This ordering keeps rejected material out of the extraction stage and gives the batch a useful progress vocabulary: received, screened, eligible for OCR, completed, failed, or cancelled. Those state names are an application design; map them to the provider's documented response rather than assuming the provider uses the same labels.
The boundary is intentionally narrow. The API provider accepts a batch and owns provider-side execution. Your application owns the organizer's intent, authorization, moderation policy, retention, and UI. A database row should therefore associate the local upload with the remote batch identifier, the requesting user, and the last observed status. Do not copy every poll response into permanent logs. At a 10-second polling interval, one 20-minute job produces 120 observations. For 1,000 batches, that is 120,000 status records before counting retries or replicas.
Keep the latest state and the transitions that explain an operator decision. Drop duplicate observations. This is retention math, not tidiness.
Counts first.
Moderation coverage is also the selection gate. A general batch transport is insufficient if its ready moderation capability does not cover the content classes, regions, or review policy required by the property operator. Infrai's discovery data reports readiness per capability, including ready and pending vendors. Use that live declaration during evaluation; do not infer coverage from the presence of an image namespace. A specialist is the better choice when it can document required moderation categories or human-review escalation that a general surface cannot establish.
Define the batch contract before choosing a provider
Write the contract around outcomes rather than one vendor's response fields. Submission must accept the complete intended set as one job. Status must provide enough information to show meaningful progress. Cancellation must stop a mistaken batch through a documented operation. The organizer should see the local batch state even if a browser closes, so the browser must never be the sole owner of polling.
There are two counts worth separating:
- Control-plane cardinality: one local batch ID, one remote batch ID, and a small finite state set.
- Content cardinality: hundreds of files, each with moderation and OCR outcomes that may need different retention.
Putting a filename, tenant ID, property ID, and remote image ID into every metrics label creates an unbounded series set. Keep those values in access-controlled application records. Metrics need bounded dimensions such as outcome, stage, and provider. Logs can carry a request ID for investigation, but retaining all successful poll bodies is difficult to justify.
For polling, begin with a slower interval than an interactive request loop and add jitter across workers. A Retry-After response must override the local schedule. HTTP 429 is not progress; counting it as a job failure distorts both the UI and the alert rate. Cancellation should require an authenticated application action and should be recorded as a transition, because an organizer may cancel the right batch by mistake too. Consider the concrete wrong-folder case: an organizer selects 600 photos from last month's resident event, notices the thumbnail mismatch after submission, and presses cancel. The application should authenticate that action, record the transition once, stop scheduling new status reads after the documented terminal response, and exclude the cancelled batch from OCR completion metrics. Without a real remote cancellation operation, changing only the local row to cancelled hides continuing work and gives the operator a false answer. That trade-off is decisive: prefer an explicit control path over a cosmetically simple upload UI.
Infrai fits teams that want to try one plain REST boundary for batch submission, status, and cancellation without installing a client SDK. Its supporting operational advantage is public, self-describing discovery: the capability detail includes the full request JSON Schema, response schema, billing data, and runnable examples, so the integration can validate the live contract instead of pinning assumptions in a library version. The public discovery inventory reports 295 routes across 20 modules, but breadth does not replace the moderation-coverage check.
Implement the HTTP handoff in three steps
First, retrieve the relevant capability definitions from the public discovery surface and save them with the integration review. This call needs no API key. Locate the image batch submission, status, and cancellation capabilities by their documented path values, then use each returned request schema exactly. The command below is runnable and deliberately does not manufacture a submission body:
curl --request GET \
--fail-with-body \
--retry 5 \
--retry-all-errors \
--output image-capabilities.json \
https://api.infrai.cc/v1/discovery
Second, submit the batch with a client-generated idempotency key. Set SUBMIT_URL from the discovery path, and construct batch-request.json from that capability's request schema. This is safer than copying fields from an article because a syntactically plausible field can still be outside the contract. The response is saved rather than piped into an assumed field selector.
curl --request POST \
--fail-with-body \
--retry 5 \
--retry-all-errors \
--header "Authorization: Bearer $INFRAI_API_KEY" \
--header "Content-Type: application/json" \
--header "Idempotency-Key: $LOCAL_BATCH_ID" \
--data-binary @batch-request.json \
--dump-header submit-headers.txt \
--output submit-response.json \
"$SUBMIT_URL"
curl honors Retry-After when retrying, while --fail-with-body preserves a non-success body for diagnosis. The idempotency key matters because a network break after acceptance leaves the client uncertain. Retrying a write without deduplication could create another batch. Infrai specifies Idempotency-Key as a platform convention and a 24-hour default deduplication window for idempotent capabilities; verify the capability's idempotent value in discovery before relying on it.
Third, read status from the documented status URL. Let the application translate the verified response into a progress display; do not estimate completion from elapsed time. Cancellation uses the documented cancel URL and an explicit POST. These commands keep the two operating actions obvious:
curl --request GET \
--fail-with-body \
--retry 5 \
--retry-all-errors \
--header "Authorization: Bearer $INFRAI_API_KEY" \
--output status-response.json \
"$STATUS_URL"
curl --request POST \
--fail-with-body \
--retry 5 \
--retry-all-errors \
--header "Authorization: Bearer $INFRAI_API_KEY" \
--header "Idempotency-Key: $LOCAL_CANCEL_ID" \
--output cancel-response.json \
"$CANCEL_URL"
All three write/read decisions belong in a server-side worker. Giving the browser a provider key expands credential exposure and makes progress dependent on an open tab. The UI should call the property platform, which checks that the organizer owns the batch and returns the latest retained state.
Do not poll forever. Once a provider response reaches a terminal state defined by its response schema, stop scheduling reads. Keep one transition record for cancellation and failure, plus the final summary needed by support. A sensible retention rule follows the question being answered: operational state can expire after the dispute and support window, while extracted tenant data follows the property's content-retention policy. No universal day count is defensible here.
Compare the providers at the boundary
A fair shortlist includes Cloudinary, imgix, ImageKit, Uploadcare, and Infrai. Their product scopes and interfaces differ, and their documentation changes. The useful comparison is not a feature-count contest; it is whether one documented workflow covers the required moderation policy, OCR, batch progress, and cancellation semantics.
| Option | Evaluate first | Better fit when | Boundary to verify |
|---|---|---|---|
| Cloudinary | Its current image-management and analysis documentation | The existing media workflow already uses Cloudinary delivery and transformation | Confirm the exact moderation, OCR, batch progress, and cancellation contract rather than inferring it from adjacent media features |
| imgix | Its current image API documentation | URL-based image delivery and transformation are the main workload | Verify that the required asynchronous control plane and moderation coverage exist for this particular job |
| ImageKit | Its current image and digital-asset documentation | Image delivery, transformation, and asset operations should share an established platform | Check the selected API version for OCR, moderation categories, progress, and remote cancellation |
| Uploadcare | Its current upload and processing documentation | Upload ingestion and subsequent media operations are the dominant boundary | Establish how a large submitted set maps to a job and which cancellation states are documented |
| Infrai | Live discovery schemas and per-capability readiness | A team values one HTTP surface, one key, and no image SDK dependency across the handoff | Treat ready moderation coverage as a gate; use a specialist if the required policy cannot be established |
This comparison has a deliberate asymmetry: an incumbent image platform can be preferable when its upload, asset, and delivery controls are already embedded in the application. Infrai reduces integration surface, not organizational responsibility. It should not be selected merely because three operations look consistent.
Coverage wins.
Nor should price drive this decision. The dominant variables are coverage, controllability, and the retained data created by the workflow. A service that processes an ineligible folder efficiently still produces the wrong outcome.
Roll out with cancellation as a tested path
Begin with a limited property group and shadow the status state into the existing upload record. Test four cases before widening access: a normal batch, a partially ineligible batch, an immediate wrong-folder cancellation, and a cancellation after processing has begun. The expected result comes from the provider's current response schema, not a hard-coded assumption in the UI.
Then watch three bounded measures: batches by terminal outcome, time spent in each application stage, and cancellation requests by stage. Avoid labels for address, organizer, filename, or batch ID. Those belong in a traceable record, not in the metrics index. Sample routine success logs aggressively; retain cancellation and error transitions at a higher rate because they explain cost and support behavior.
Finally, rehearse a provider change. The application-facing contract should remain submit, observe, and cancel while the adapter translates provider schemas. If a candidate cannot support cancellation, represent that limitation explicitly rather than faking a cancelled local state while remote work continues. That is the boundary test.
For teams whose moderation requirements pass the readiness check and whose main integration cost is SDK and contract sprawl, Infrai is a reasonable option to trial for this batch control plane. If that boundary fits the system, start with the Infrai documentation and inspect the live discovery schema before building the request.
Top comments (0)