> ## Documentation Index
> Fetch the complete documentation index at: https://www.seam.co/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Get Started with Arlo Cameras

> Install a Seam SDK, connect an Arlo account, retrieve camera devices, receive motion events, and retrieve event recordings. Beta.

## Overview

Seam provides a universal API to connect and control many brands of devices. This guide provides a rapid introduction to connecting your [Arlo](/docs/device-and-system-integration-guides/arlo-cameras) cameras to Seam, retrieving them as devices, receiving their motion events, and retrieving event recordings.

To learn more about other device brands supported by Seam, head over to our [integration page](https://www.seam.co/supported-devices-and-systems).

<Warning>
  Arlo cameras are in **beta**. Seam turns on Arlo, camera events, event media, and live video for each workspace separately, so [contact Seam](mailto:support@seam.co) to enable the ones you need for your workspace, including your sandbox workspace, before you follow this guide.
</Warning>

***

## 1 — Install Seam SDK

Seam provides client libraries for many languages, such as JavaScript, Python, Ruby, PHP, and others, as well as a Postman collection and [OpenAPI](https://connect.getseam.com/openapi.json) spec.

* JavaScript / TypeScript ([npm](https://www.npmjs.com/package/seam), [GitHub](https://github.com/seamapi/javascript))
* Python ([pip](https://pypi.org/project/seam/), [GitHub](https://github.com/seamapi/python))
* Ruby Gem ([rubygem](https://rubygems.org/gems/seam), [GitHub](https://github.com/seamapi/ruby))
* PHP ([packagist](https://packagist.org/packages/seamapi/seam), [GitHub](https://github.com/seamapi/php))
* C# ([nuget](https://www.nuget.org/packages/Seam), [GitHub](https://github.com/seamapi/csharp))
* Java ([Maven](https://central.sonatype.com/artifact/co.seam/java), [GitHub](https://github.com/seamapi/java))

<CodeGroup>
  ```bash JavaScript theme={"dark"}
  npm i seam
  ```

  ```bash Python theme={"dark"}
  pip install seam
  # For some development environments, use pip3 in this command instead of pip.
  ```

  ```bash Ruby theme={"dark"}
  bundle add seam
  ```

  ```bash PHP theme={"dark"}
  composer require seamapi/seam
  ```

  ```bash C# theme={"dark"}
  Install using nuget: https://www.nuget.org/packages/Seam
  ```

  ```bash Java theme={"dark"}
  // Add to your pom.xml or build.gradle — see Maven Central for details.
  ```

  ```bash cURL (bash) theme={"dark"}
  # cURL is already installed on most systems. No additional installation needed.
  # Export your API key as an environment variable:
  export SEAM_API_KEY=seam_test2ZTo_0mEYQW2TvNDCxG5Atpj85Ffw
  ```
</CodeGroup>

Once installed, [sign up for Seam](https://console.seam.co/) to get your API key, and export it as an environment variable:

```bash theme={"dark"}
export SEAM_API_KEY=seam_test2ZTo_0mEYQW2TvNDCxG5Atpj85Ffw
```

<Info>
  This guide uses a Sandbox Workspace. Only virtual devices can be connected. If
  you need to connect a real Arlo account, use a non-sandbox workspace and API
  key.
</Info>

***

## 2 — Link an Arlo Account with Seam

To use Arlo cameras through the Seam API, you must first authorize your Seam workspace against your Arlo account. To do so, Seam provides [Connect Webviews](/docs/core-concepts/connect-webviews): pre-built UX flows that walk you through signing in to Arlo and completing two-step verification.

Arlo is a beta provider, so include `arlo` in the Connect Webview's `accepted_providers` list. The Arlo login in the Connect Webview works only after Seam turns on Arlo for your workspace, including your sandbox workspace.

#### Request a Connect Webview

<CodeGroup>
  ```javascript JavaScript theme={"dark"}
  import { Seam } from 'seam'

  const seam = new Seam()

  const connectWebview = await seam.connectWebviews.create({
    accepted_providers: ['arlo'],
  })

  console.log(connectWebview.login_successful) // false

  // Send the webview URL to your user
  console.log(connectWebview.url)
  ```

  ```python Python theme={"dark"}
  from seam import Seam

  seam = Seam()

  webview = seam.connect_webviews.create(
      accepted_providers=["arlo"]
  )

  assert webview.login_successful is False

  # Send the webview URL to your user
  print(webview.url)
  ```

  ```ruby Ruby theme={"dark"}
  require "seam"

  seam = Seam.new()

  webview = seam.connect_webviews.create(
    accepted_providers: ["arlo"]
  )

  puts webview.login_successful # false

  # Send the webview URL to your user
  puts webview.url
  ```

  ```php PHP theme={"dark"}
  <?php
  use Seam\SeamClient;

  $seam = new SeamClient("YOUR_API_KEY");

  $webview = $seam->connect_webviews->create(
    accepted_providers: ["arlo"]
  );

  echo $webview->login_successful; // false

  // Send the webview URL to your user
  echo $webview->url;
  ```

  ```csharp C# theme={"dark"}
  using Seam.Client;

  var seam = new SeamClient(apiToken: "YOUR_API_KEY");

  var webview = seam.ConnectWebviews.Create(
    acceptedProviders: new List<string> { "arlo" }
  );

  Console.WriteLine(webview.LoginSuccessful); // false

  // Send the webview URL to your user
  Console.WriteLine(webview.Url);
  ```

  ```java Java theme={"dark"}
  import co.seam.Seam;
  import co.seam.api.types.ConnectWebview;

  Seam seam = Seam.builder().apiKey("YOUR_API_KEY").build();

  ConnectWebview webview = seam.connectWebviews().create(
    ConnectWebviewsCreateRequest.builder()
      .acceptedProviders(List.of("arlo"))
      .build()
  );

  System.out.println(webview.getLoginSuccessful()); // false

  // Send the webview URL to your user
  System.out.println(webview.getUrl());
  ```

  ```bash cURL (bash) theme={"dark"}
  curl -X 'POST' \
    'https://connect.getseam.com/connect_webviews/create' \
    -H "Authorization: Bearer ${SEAM_API_KEY}" \
    -H 'Content-Type: application/json' \
    -d '{
      "accepted_providers": ["arlo"]
    }'
  ```
</CodeGroup>

#### Authorize Your Workspace

Navigate to the URL returned by the Webview object. Since you are using a sandbox workspace, complete the login flow by entering the Arlo [sandbox test account](./sandbox-arlo-cameras) credentials below:

* **email:** [arlo-test@example.com](mailto:arlo-test@example.com)
* **password:** arlo-test-password
* **verification code:** 123456

Confirm the Connect Webview was successful by querying its status:

<CodeGroup>
  ```javascript JavaScript theme={"dark"}
  const updatedWebview = await seam.connectWebviews.get(
    connectWebview.connect_webview_id,
  )

  console.log(updatedWebview.login_successful) // true
  ```

  ```python Python theme={"dark"}
  updated_webview = seam.connect_webviews.get(
      connect_webview_id=webview.connect_webview_id
  )

  assert updated_webview.login_successful  # true
  ```

  ```ruby Ruby theme={"dark"}
  updated_webview = seam.connect_webviews.get(
    connect_webview_id: webview.connect_webview_id
  )

  puts updated_webview.login_successful # true
  ```

  ```php PHP theme={"dark"}
  <?php
  $updated_webview = $seam->connect_webviews->get(
    connect_webview_id: $webview->connect_webview_id
  );

  echo $updated_webview->login_successful; // true
  ```

  ```csharp C# theme={"dark"}
  var updatedWebview = seam.ConnectWebviews.Get(
    connectWebviewId: webview.ConnectWebviewId
  );

  Console.WriteLine(updatedWebview.LoginSuccessful); // true
  ```

  ```java Java theme={"dark"}
  ConnectWebview updatedWebview = seam.connectWebviews().get(
    ConnectWebviewsGetRequest.builder()
      .connectWebviewId(webview.getConnectWebviewId())
      .build()
  );

  System.out.println(updatedWebview.getLoginSuccessful()); // true
  ```

  ```bash cURL (bash) theme={"dark"}
  curl -X 'POST' \
    'https://connect.getseam.com/connect_webviews/get' \
    -H "Authorization: Bearer ${SEAM_API_KEY}" \
    -H 'Content-Type: application/json' \
    -d "{
      \"connect_webview_id\": \"${CONNECT_WEBVIEW_ID}\"
    }"
  ```
</CodeGroup>

***

## 3 — Retrieve Arlo Camera Devices

After an Arlo account is linked with Seam, you can retrieve its cameras and video doorbells as devices with the `arlo_camera` device type.

<CodeGroup>
  ```javascript JavaScript theme={"dark"}
  const cameras = await seam.devices.list({ device_type: 'arlo_camera' })

  const camera = cameras[0]

  console.log(camera.properties.online) // true
  console.log(camera.can_stream_live_video) // true

  console.log(camera)
  /*
  {
    device_id: '...',
    device_type: 'arlo_camera',
    can_stream_live_video: true,
    properties: {
      online: true,
      manufacturer: 'arlo',
      name: 'Living Room Camera',
      arlo_metadata: {
        device_id: '...',
        device_name: 'Living Room Camera',
        model_id: 'VMC3060A'
      }
    },
    ...
  }
  */
  ```

  ```python Python theme={"dark"}
  cameras = seam.devices.list(device_type="arlo_camera")

  camera = cameras[0]

  assert camera.properties["online"] is True
  assert camera.can_stream_live_video is True

  print(camera)
  # Device(
  #   device_id='...',
  #   device_type='arlo_camera',
  #   can_stream_live_video=True,
  #   properties={
  #     'online': True,
  #     'manufacturer': 'arlo',
  #     'name': 'Living Room Camera',
  #     'arlo_metadata': {
  #       'device_id': '...',
  #       'device_name': 'Living Room Camera',
  #       'model_id': 'VMC3060A'
  #     }
  #   },
  #   ...
  # )
  ```

  ```ruby Ruby theme={"dark"}
  camera = seam.devices.list(device_type: "arlo_camera").first

  puts camera.properties.online # true

  puts camera
  ```

  ```php PHP theme={"dark"}
  <?php
  $cameras = $seam->devices->list(device_type: "arlo_camera");

  $camera = $cameras[0];

  echo $camera->properties->online; // true
  ```

  ```csharp C# theme={"dark"}
  var cameras = seam.Devices.List(
    deviceType: Seam.Api.Devices.ListRequest.DeviceTypeEnum.ArloCamera
  );

  var camera = cameras[0];

  Console.WriteLine(camera.Properties.Online); // true
  ```

  ```java Java theme={"dark"}
  var cameras = seam.devices().list(
    DevicesListRequest.builder()
      .deviceType("arlo_camera")
      .build()
  );

  var camera = cameras.get(0);

  System.out.println(camera.getProperties().getOnline()); // true
  ```

  ```bash cURL (bash) theme={"dark"}
  curl -X 'POST' \
    'https://connect.getseam.com/devices/list' \
    -H "Authorization: Bearer ${SEAM_API_KEY}" \
    -H 'Content-Type: application/json' \
    -d '{
      "device_type": "arlo_camera"
    }'
  ```
</CodeGroup>

***

## 4 — Receive Motion Events

When a connected Arlo camera detects motion, Seam creates a `camera.activated` event with `activation_reason` set to `motion_detected`. To receive these events as they happen, [set up a webhook](/docs/developer-tools/webhooks). You can also [list events](/docs/api/events/list) for the camera.

<Info>
  The Arlo sandbox doesn't simulate motion, so this step and the next return no events or media in a sandbox workspace. Use a real Arlo account in a non-sandbox workspace to see them.
</Info>

<CodeGroup>
  ```javascript JavaScript theme={"dark"}
  const events = await seam.events.list({
    device_id: camera.device_id,
    event_type: 'camera.activated',
    since: '2026-01-01T00:00:00Z',
  })

  console.log(events)
  ```

  ```python Python theme={"dark"}
  events = seam.events.list(
      device_id=camera.device_id,
      event_type="camera.activated",
      since="2026-01-01T00:00:00Z"
  )

  print(events)
  ```

  ```ruby Ruby theme={"dark"}
  events = seam.events.list(
    device_id: camera.device_id,
    event_type: "camera.activated",
    since: "2026-01-01T00:00:00Z"
  )

  puts events.inspect
  ```

  ```php PHP theme={"dark"}
  <?php
  $events = $seam->events->list(
    device_id: $camera->device_id,
    event_type: "camera.activated",
    since: "2026-01-01T00:00:00Z"
  );

  echo json_encode($events);
  ```

  ```csharp C# theme={"dark"}
  var events = seam.Events.List(
    deviceId: camera.DeviceId,
    eventType: Seam.Api.Events.ListRequest.EventTypeEnum.CameraActivated,
    since: "2026-01-01T00:00:00Z"
  );

  foreach (var cameraEvent in events)
  {
    Console.WriteLine(cameraEvent);
  }
  ```

  ```java Java theme={"dark"}
  var events = seam.events().list(
    EventsListRequest.builder()
      .deviceId(camera.getDeviceId())
      .eventType("camera.activated")
      .since("2026-01-01T00:00:00Z")
      .build()
  );

  System.out.println(events);
  ```

  ```bash cURL (bash) theme={"dark"}
  curl -X 'POST' \
    'https://connect.getseam.com/events/list' \
    -H "Authorization: Bearer ${SEAM_API_KEY}" \
    -H 'Content-Type: application/json' \
    -d "{
      \"device_id\": \"${DEVICE_ID}\",
      \"event_type\": \"camera.activated\",
      \"since\": \"2026-01-01T00:00:00Z\"
    }"
  ```
</CodeGroup>

**Example `camera.activated` event:**

```json theme={"dark"}
{
  "event_id": "0b7f0d6a-5b1e-4d0c-9d5c-2d8f6a3e1c44",
  "event_type": "camera.activated",
  "workspace_id": "398d80b7-3f96-47c2-b85a-6f8ba21d07be",
  "device_id": "a83690b2-2b70-409a-9a94-426699b84c97",
  "connected_account_id": "c9d3f2a1-7b4e-4f0a-8e2d-5a6b7c8d9e0f",
  "activation_reason": "motion_detected",
  "media_ids": [
    "01a0d985-621c-7b3e-9f2d-4a5b6c7d8e9f",
    "01a0d985-621c-7c4f-8a3e-5b6c7d8e9f0a"
  ],
  "video_url": "https://connect.getseam.com/media/get?media_id=01a0d985-621c-7b3e-9f2d-4a5b6c7d8e9f&format=redirect",
  "image_url": "https://connect.getseam.com/media/get?media_id=01a0d985-621c-7c4f-8a3e-5b6c7d8e9f0a&format=redirect",
  "occurred_at": "2026-09-25T17:03:12.000Z",
  "created_at": "2026-09-25T17:03:12.412Z"
}
```

***

## 5 — Retrieve the Event Recording

When event media is turned on for your workspace, each Arlo `camera.activated` event lists `media_ids`: one for the video clip and one for a thumbnail image. Seam copies the clip from the Arlo cloud library, converts it to MP4 with H.264 video so that browsers can play it, and extracts the thumbnail from it.

Pass each ID to [`/media/get`](/docs/capability-guides/cameras/retrieve-event-media). The response's `media_type` tells you whether it's the clip (`video`) or the thumbnail (`image`).

<Info>
  Recordings require an Arlo subscription that includes cloud recording. Without one, the media ends in the `unavailable` status. Arlo usually finishes a clip within a minute of the motion, so the media is `pending` until then.
</Info>

<CodeGroup>
  ```javascript JavaScript theme={"dark"}
  const { media } = await seam.media.get({
    media_id: '01a0d985-621c-7b3e-9f2d-4a5b6c7d8e9f',
  })

  console.log(media.status, media.media_type, media.url)
  ```

  ```python Python theme={"dark"}
  media = seam.media.get(
      media_id="01a0d985-621c-7b3e-9f2d-4a5b6c7d8e9f"
  )

  print(media.status, media.media_type, media.url)
  ```

  ```ruby Ruby theme={"dark"}
  media = seam.media.get(
    media_id: "01a0d985-621c-7b3e-9f2d-4a5b6c7d8e9f"
  )

  puts media.status, media.media_type, media.url
  ```

  ```php PHP theme={"dark"}
  <?php
  $media = $seam->media->get(
    media_id: "01a0d985-621c-7b3e-9f2d-4a5b6c7d8e9f"
  );

  echo $media->status, $media->media_type, $media->url;
  ```

  ```csharp C# theme={"dark"}
  var media = seam.Media.Get(
    mediaId: "01a0d985-621c-7b3e-9f2d-4a5b6c7d8e9f"
  );

  Console.WriteLine($"{media.Status} {media.MediaType} {media.Url}");
  ```

  ```java Java theme={"dark"}
  var media = seam.media().get(
    MediaGetRequest.builder()
      .mediaId("01a0d985-621c-7b3e-9f2d-4a5b6c7d8e9f")
      .build()
  );

  System.out.println(media.getStatus() + " " + media.getMediaType() + " " + media.getUrl());
  ```

  ```bash cURL (bash) theme={"dark"}
  curl -X 'POST' \
    'https://connect.getseam.com/media/get' \
    -H "Authorization: Bearer ${SEAM_API_KEY}" \
    -H 'Content-Type: application/json' \
    -d '{
      "media_id": "01a0d985-621c-7b3e-9f2d-4a5b6c7d8e9f"
    }'
  ```
</CodeGroup>

**Example response:**

```json theme={"dark"}
{
  "media": {
    "media_id": "01a0d985-621c-7b3e-9f2d-4a5b6c7d8e9f",
    "workspace_id": "398d80b7-3f96-47c2-b85a-6f8ba21d07be",
    "device_id": "a83690b2-2b70-409a-9a94-426699b84c97",
    "event_id": "0b7f0d6a-5b1e-4d0c-9d5c-2d8f6a3e1c44",
    "media_type": "video",
    "content_type": "video/mp4",
    "status": "available",
    "url": "https://media.getseam.com/...",
    "expires_at": "2026-10-02T17:04:40.000Z",
    "created_at": "2026-09-25T17:03:12.412Z"
  }
}
```

The `url` is a signed link that expires within minutes, so store the `media_id` rather than the `url`, and call [`/media/get`](/docs/api/media/get) again for a new URL. The response has no field for when the URL expires. `expires_at` is when the media itself stops being available: Seam keeps stored Arlo media for 7 days. For polling, statuses, and browser playback, see [Retrieve Event Media](/docs/capability-guides/cameras/retrieve-event-media).

***

## 6 — Stream Live Video

You can stream an Arlo camera's live video to a browser over WebRTC when its `can_stream_live_video` capability flag is `true` and live video is turned on for your workspace. The flag means the camera supports live video and is online. It doesn't reflect whether live video is turned on for your workspace: if it isn't, [`/cameras/live_views/create`](/docs/api/cameras/live_views/create) returns a `camera_not_available` error. The flag is `false` while the camera is offline. Live view uses a [client session token](/docs/core-concepts/authentication/client-session-tokens) scoped to the camera, so your users' browsers never see your API key. For the full flow, see [Stream Live Video](/docs/capability-guides/cameras/stream-live-video).

***

## Next Steps

Now that you've completed this guide, you can try to connect a real Arlo account. To do so, make sure to switch to a non-sandbox workspace and API key, as real devices cannot be connected to sandbox workspaces. See the [Arlo Setup Guide](./arlo-setup-guide) for two-step verification and subscription requirements.

In addition, if you'd like to explore other aspects of Seam, here is a list of helpful resources:

* [Receiving webhooks](/docs/developer-tools/webhooks) for [device events](/docs/api/events/list)
* [Stream Live Video](/docs/capability-guides/cameras/stream-live-video)
* [Retrieve Event Media](/docs/capability-guides/cameras/retrieve-event-media)
* [Core Concepts](/docs/core-concepts/overview)

If you have any questions or want to report an issue, email us at [support@seam.co](mailto:support@seam.co).
