Preview API

Preview upload is a three-step flow. Reserve upload slots, PUT each declared artifact to its returned URL, then finalize the reservation. Use a key with the preview_upload scope for every step.

Reserve upload slots

POST https://contrast.dev/api/v1/previews

{
"contentHash": "<sha256 of the uncompressed bundle>",
"bundleSizeBytes": 182430,
"bundleContentType": "application/javascript",
"bundleOrigin": "http://localhost:8081",
"entry": "index",
"isTransformed": true,
"deviceSpec": { "width": 393, "height": 852 },
"files": []
}

The response contains shareId, a short-lived reservation token, and presigned slots for the bundle and every declared file or recording artifact. Each slot has putUrl, objectKey, and contentType.

PUT the exact declared bytes directly to every putUrl. Use the returned contentType header.

Finalize

POST https://contrast.dev/api/v1/previews/finalize

{ "token": "<reservation token>" }

The API verifies that all declared objects arrived and returns the hosted URL:

{
"id": "preview id",
"url": "https://sootsim.com/preview/preview-id",
"filesStored": 0,
"createdAt": 1784690000000
}

The finalizing credential must resolve to the account that reserved the upload.

Read metadata

GET https://contrast.dev/api/v1/previews/{id} returns metadata only when the preview belongs to the authenticated account. The response includes its hosted url, device details, files, recording artifacts, Git provenance, and account attribution.

Set billingKind to test_run when the uploaded artifact is a billed test run. That request also requires test_runs. See Test Runs.

Ready to build?

Run your React Native app in the browser. No simulators, no native toolchain, no waiting.

curl -fsSL https://sootsim.com/install.sh | sh