/media/get to get the media’s status and a short-lived signed URL for downloading or playing it.
How It Works
- Seam creates a
camera.activatedordevice.doorbell_rangevent. The event’smedia_idsarray lists one ID for each piece of media Seam expects for the event. - You call
/media/getwith amedia_id. Seam returns amediaobject with astatusand, once the media is ready, a signedurl. - You download or play the media from
urlright away. The URL expires within minutes, so call/media/getagain whenever you need a new one.
media_id, not the url. Signed URLs expire within minutes, while a media ID stays valid for about 30 days. After that, /media/get returns media_not_found for it.
Supported Providers
For Arlo and Tapo, Seam copies the clip into Seam’s private storage and extracts a JPEG thumbnail from it. Seam converts clips to MP4 with H.264 video so that browsers can play them. Ring media stays with Ring: Seam requests a signed URL from Ring each time you call
/media/get.
Before You Begin
To retrieve event media, you need:- For Arlo and Tapo, a workspace with camera events and event media turned on. Ring event media doesn’t need to be turned on.
- A connected account with a supported camera or doorbell.
- A webhook subscribed to
camera.activatedand, for Ring doorbells,device.doorbell_rang. - An API key, or a client session token that has access to the device.
Step 1: Receive a Camera Event
Subscribe your webhook tocamera.activated and device.doorbell_rang. Verify the webhook signature, then store the event’s media_ids along with its event_id and device_id.
Example camera.activated event:
media_idsdoesn’t guarantee any order. Call/media/getfor each ID and readmedia_typeto find the clip (video) and the thumbnail (image).media_idsis missing when Seam isn’t capturing media for the event. For example, event media might not be turned on for an Arlo or Tapo workspace, or the provider might not supply media for that event type.motion_sub_type(human,vehicle,package, orother) is included when the provider reports it.video_urlandimage_urlare still included for compatibility. They point to/media/getwithformat=redirect, and requests to them need the same authentication as any other Seam API request. New integrations should usemedia_ids.
For Arlo and Tapo, media usually isn’t ready when the event arrives. Seam sends the event first, and then retrieves the recording in the background. Ring media is
available as soon as the event arrives.Step 2: Get the Media
Call/media/get with a media_id. The default format is json, which returns the media object.
Request:
Media Object
See the media object reference for the complete property list.
The response has no field for when
url expires, and the lifetime varies by provider. Treat every URL as valid for only a few minutes, and call /media/get again for a new one rather than caching it.
Media Statuses
pending is the only status that changes. After the media’s expires_at passes, /media/get returns a media_not_available error for it. About 30 days after the event, Seam deletes the media record entirely, and /media/get returns media_not_found.
Step 3: Wait for Pending Media
Seam can’t retrieve an Arlo or Tapo recording until the provider finishes it, so media often stayspending for a minute or more after the event. Seam doesn’t send an event when media becomes available, so poll /media/get with backoff:
- Wait about 15 seconds after the event before the first request.
- Double the delay after each
pendingresponse, up to 30 seconds between requests. - Stop after about 10 minutes and treat the media as unavailable.
- Poll from a background job, not from the webhook handler. Return a
2xxfrom the webhook handler as soon as you store the event.
JavaScript
Step 4: Use the Signed URL
Theurl is a signed, short-lived link to the media file. It expires within minutes, and the exact lifetime varies by provider. The response doesn’t say when: expires_at is when the media itself stops being available, not when the URL expires.
- Don’t store the URL. Store the
media_idand call/media/getwhen you need a URL. - Request a new URL when playback fails. A video player can request byte ranges from the URL long after the page loads, for example when the user seeks. If the player reports an error, call
/media/getagain and set the new URL as the source. - Keep the URL private. Anyone who has the URL can download the media until it expires. Don’t log it or put it in analytics events.
- Keep your own copy if you need it longer. Seam keeps stored Arlo and Tapo media for 7 days, and
expires_attells you when. After that,/media/getreturnsmedia_not_available. Ring media has noexpires_at: it’s available for up to 30 days, subject to the retention of the Ring account’s Ring Protect plan.
JSON vs. Redirect
/media/get accepts a format parameter:
Browsers can’t add an
Authorization header to an <img> or <video> element’s request, so you can’t point one straight at /media/get. In a browser, request the JSON format with your client session token, then set the returned url as the element’s src. This works for media that Seam stores, such as Arlo clips:
JavaScript
cURL
302. See Errors.
Authorization
/media/get accepts the same credentials as other Seam read endpoints: an API key, a personal access token with a workspace, or a client session token.
A client session can only get media for the devices it has access to. That is, devices in the connected accounts, Connect Webviews, or user identity that you associated with the client session when you created it, or, for a client session created with a customer_key, that customer’s devices. For any other device’s media, Seam returns media_not_found, the same error it returns for an ID that doesn’t exist, so a client can’t probe for media in other accounts.
Use client sessions to show media in your users’ browsers or mobile apps without exposing your API key.
Errors
Provider Notes
TP-Link Tapo
- Seam retrieves the clip from the camera’s microSD card through the paired Seam Bridge, so the Bridge and the camera must stay online after the event.
- Seam needs the Tapo account password, which is the password for the Tapo app, not the Camera Account password. Enter it in the optional Tapo account password field of the Connect Webview. For a camera connected without it, media ends up
unavailable. To add it, reconnect the camera. Recordings start with the next motion event. See Tapo event recordings. - Without a microSD card, or when the card has no recording that contains the event, the media ends up
unavailable. - The sandbox Tapo camera has no microSD recordings.
Arlo
- Seam retrieves the clip from the Arlo cloud library. Without a subscription that includes cloud recording, Arlo stores no recording, and the media ends up
unavailable. - Arlo clips are often recorded in HEVC. Seam converts them to H.264 so that browsers can play them.
Ring
- Ring media is available for both
camera.activatedanddevice.doorbell_rangevents. - Ring only keeps clips for accounts with an active Ring Protect subscription.
- Seam requests a new signed URL from Ring on each
/media/getcall. Ring media isavailableas soon as the event arrives, and itsexpires_atisnull. If Ring no longer has the recording,/media/getreturnsmedia_not_available. - Ring video URLs may not play directly in a browser. See JSON vs. Redirect.
Next Steps
- Get Media: Full request and response reference for
/media/get. - Stream live video: Watch a camera’s live feed in the browser over WebRTC.
- Webhooks: Receive and verify camera events.
- Client session tokens: Give your users’ browsers scoped access to their devices.