Upload a photo
Send the photo, get back an image resource that is already preprocessing. One request — the file goes in the body; there is no separate upload step against storage.
JPEG, PNG and WebP only, 4MB maximum. Both limits are enforced against the bytes actually sent: the declared content type is not trusted, so a file that decodes as anything else is rejected even when it is labeled as one of the three.
The photo is resized server-side before preprocessing, so width and height on the response describe the stored image, not your original.
Preprocessing begins immediately but does not block this call — poll the returned resource until it is ready.
This is the one pipeline call that never requires a visitor token on any instance, and it is where tokens come from. Sent without X-Viewa-Visitor-Token, it mints a new anonymous shopper and returns visitor on the created image. Sent with one, the upload attaches to that existing shopper — their earlier images, areas, renders and history stay reachable — and visitor comes back with a refreshed expiresAt. Either way the block is present, so the client always has a current token to store.
Publishable key (browser-safe), sent as Authorization: Bearer pk_…. This is the lower API-key tier and is sufficient for browser-safe routes that require the pk tier. Requests using a publishable key are additionally validated against the key's domain allowlist via the Origin header. Used for upload, areas, renders, polling, catalog reads, and history (history additionally requires a visitor token).
In: header
Header Parameters
Repeat this value to retry an upload safely: the retry returns the image the first call created instead of processing the photo again, together with the visitor that upload created — which is how a client recovers when the original response was lost. Scoped to your instance, so your keys never collide with another integrator's. Reusing another shopper's key returns idempotency_key_reused.
length <= 200The photo, either as a file part in a multipart form or as the raw request body. The server stores a normalised copy: EXIF orientation applied, resized to fit 1024 px, re-encoded as JPEG (quality 90) with the camera EXIF block kept (orientation reset to 1) so the depth pass can read the lens data. HEIC is not accepted; iOS transcodes to JPEG when the file input's accept list excludes it.
TypeScript Definitions
Use the request body type in TypeScript.
Response Body
application/json
application/problem+json
application/problem+json
application/problem+json
application/problem+json
application/problem+json
application/problem+json
application/problem+json
curl -X POST "https://example.com/images" \ -F file="string"{ "id": "img_7bQ2mR9vXpL4dK1sZeCt", "status": "preprocessing", "width": 1024, "height": 768, "url": "https://api.viewa.com/api/v1/images/img_7bQ2mR9vXpL4dK1sZeCt/file", "error": { "code": "preprocessing_failed", "detail": "string" }, "visitor": { "id": "vis_5nQ8xR2wKt7bZm3LpVdC", "token": "string", "expiresAt": "2019-08-24T14:15:22Z" }}