---
title: "Server-side handoff: give us a public https URL of the walkthrough instead of uploading it from a browser. Secret key only. We fetch it (up to 500 MB, streamed) and the job runs exactly as an upload would — poll GET /jobs/{id}. Needs the stored contact email and consent, like /upload-url. Replaces /upload-url, /upload-complete and /submit for a caller that already holds the file. A job whose fetch failed (`error`) may be handed a new URL. Counts toward the mover's daily analysis cap (429)."
method: POST
path: "/jobs/{id}/video"
---

# Server-side handoff: give us a public https URL of the walkthrough instead of uploading it from a browser. Secret key only. We fetch it (up to 500 MB, streamed) and the job runs exactly as an upload would — poll GET /jobs/{id}. Needs the stored contact email and consent, like /upload-url. Replaces /upload-url, /upload-complete and /submit for a caller that already holds the file. A job whose fetch failed (\`error\`) may be handed a new URL. Counts toward the mover's daily analysis cap (429).

`POST /jobs/{id}/video`

## Request

- Base URL: `https://widget.reelquoteai.com/api/v1`
- URL: `https://widget.reelquoteai.com/api/v1/jobs/{id}/video`
- Auth: HTTP bearer

## Request body

- object
  - `url` string, required: Public https URL that serves the video (a signed cloud-storage link is ideal). Private hosts and http are refused.
  - `content_type` string: A video/* MIME type when you know it; otherwise the host's Content-Type must be video/*
  - `consent` boolean, required: Must be true: the customer agrees the video will be analysed and shared with the mover.

## Response `202`

Accepted; the fetch runs in the background. Status goes uploading → processing → complete (or error with a plain-language reason if the URL did not serve a video). Under a test key the job completes at once with the fixed inventory.

- object
  - `job_id` string
  - `status` 'uploading' | 'complete'
  - `source` 'url': Absent on a sandbox job
  - `sandbox` boolean: Only present (true) on a sandbox job

## Other responses

- `400`: `invalid_request` — A field is missing, malformed or not allowed in this state. `message` says which. `secret_key_in_url` — A secret key was sent as `?k=`. Secret keys go in the Authorization header only.
- `401`: `unauthorized` — No key, an unknown key, or a revoked key.
- `403`: `secret_key_required` — The endpoint is server-only; a publishable key cannot reach it. `insufficient_scope` — The key does not carry the scope this call needs (named in `message`). Mint one that does from the keys page or POST /keys. `key_rotated` — The calling key has been rotated and is in its grace period: it still serves jobs and quotes, but key management and the delivery log belong to its replacement. `mode_mismatch` — A test key tried to manage a live key. Live keys manage both modes; test keys manage test keys only.
- `404`: `not_found` — No such job for this key, or no such endpoint.
- `409`: `last_publishable_key` — The only live publishable key cannot be revoked — the widget stops without one. Rotate it instead. `key_already_rotated` — That key was already rotated. A key is rotated once; its replacement is the one to use and to rotate next. `webhook_paused` — That webhook endpoint is paused; turn it back on before replaying a delivery to it. `video_in_flight` — A video is already being fetched for this job (POST /jobs/{id}/video). Poll GET /jobs/{id}. `video_already_supplied` — The job already has a video and has moved past upload. Start a new job for a different walkthrough. `no_rate_card` — The mover has no active rate card, so nothing can be priced yet. `ballpark_not_bookable` — Only a firm quote from a filmed walkthrough can be booked. `already_requested` — The job is already booked or awaiting the mover, so the move date can no longer change here. Contact the mover. `idempotency_in_progress` — A request with the same Idempotency-Key is still being processed. Obey `Retry-After` (1 s) and retry with the same key.
- `429`: `rate_limited` — Per-key limit (60/min publishable, 300/min secret), the mover's daily ballpark or video-analysis cap, or a visitor's daily catalog-search cap. Obey `Retry-After`. Carries `Retry-After` in seconds.
- `503`: `address_lookup_unavailable` — Address autocomplete is not configured or is down. Send the address as free text. `upload_unavailable` — Video storage is temporarily unavailable. Retry in a few minutes. `queue_unavailable` — The job could not be started just now; nothing was changed. Repeat the same request after `Retry-After`.

---

[API](https://skmtc.dev/reelquoteai/apis/reelquoteai-us-api.md) · [All operations](https://skmtc.dev/reelquoteai/apis/reelquoteai-us-api/llms.txt) · [OpenAPI document](https://skmtc.dev/reelquoteai/apis/reelquoteai-us-api/revisions/56c304752192?raw)
