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

# Using Cloud Keys

> Learn how to use cloud keys to trigger web-based unlocks attributed to specific user identities in the ACS audit trail.

Cloud keys are a web-based unlock access method. When you use a cloud key, the door unlocks over the internet through the ACS cloud connection. Each unlock is attributed to the specific user identity in the ACS audit trail, rather than being recorded as a generic system action.

Cloud keys are ideal for:

* **Web pass shared via link:** Send your user a URL that triggers a remote unlock when tapped.
* **Embedded unlock in your app:** Add an unlock button to your web or mobile app that calls the Seam API to unlock the door.

## Before You Begin

To use cloud keys, you need:

* A [Seam API key](https://console.seam.co)
* A connected ACS that supports cloud key unlocks
* A [user identity](/capability-guides/mobile-access/managing-mobile-app-user-accounts-with-user-identities) representing the person who will unlock the door
* An entrance that supports cloud key unlocks (`can_unlock_with_cloud_key` is `true`)

## Step 1: Verify Entrance Support

List the entrances for your ACS and confirm that `can_unlock_with_cloud_key` is `true` for the entrance you want to unlock.

<CodeGroup>
  ```javascript JavaScript theme={null}
  const entrances = await seam.acs.entrances.list({
    acs_system_id: 'c359cba2-8ef2-47fc-bee0-1c7c2a886339',
  })

  const cloudKeyEntrances = entrances.filter(
    (e) => e.can_unlock_with_cloud_key
  )
  ```

  ```python Python theme={null}
  entrances = seam.acs.entrances.list(
      acs_system_id="c359cba2-8ef2-47fc-bee0-1c7c2a886339"
  )

  cloud_key_entrances = [
      e for e in entrances if e.can_unlock_with_cloud_key
  ]
  ```

  ```ruby Ruby theme={null}
  entrances = seam.acs.entrances.list(
    acs_system_id: "c359cba2-8ef2-47fc-bee0-1c7c2a886339"
  )

  cloud_key_entrances = entrances.select do |e|
    e.can_unlock_with_cloud_key
  end
  ```

  ```php PHP theme={null}
  $entrances = $seam->acs->entrances->list(
    acs_system_id: "c359cba2-8ef2-47fc-bee0-1c7c2a886339"
  );

  $cloudKeyEntrances = array_filter(
    $entrances,
    fn($e) => $e->can_unlock_with_cloud_key
  );
  ```

  ```csharp C# theme={null}
  var entrances = seam.Acs.Entrances.List(
    acsSystemId: "c359cba2-8ef2-47fc-bee0-1c7c2a886339"
  );

  var cloudKeyEntrances = entrances
    .Where(e => e.CanUnlockWithCloudKey)
    .ToList();
  ```

  ```java Java theme={null}
  var entrances = seam.acs().entrances().list(
    AcsEntrancesListRequest.builder()
      .acsSystemId("c359cba2-8ef2-47fc-bee0-1c7c2a886339")
      .build()
  );
  ```

  ```bash cURL theme={null}
  curl -X 'POST' \
    'https://connect.getseam.com/acs/entrances/list' \
    -H "Authorization: Bearer ${SEAM_API_KEY}" \
    -H 'Content-Type: application/json' \
    -d '{
    "acs_system_id": "c359cba2-8ef2-47fc-bee0-1c7c2a886339"
  }'
  ```
</CodeGroup>

**Output:**

```json theme={null}
[
  {
    "acs_entrance_id": "f74e4879-5991-4e2f-a368-888983dcfbfc",
    "display_name": "Main Entrance",
    "can_unlock_with_cloud_key": true,
    ...
  }
]
```

## Step 2: Create an Access Grant with a Cloud Key

Create an [Access Grant](/use-cases/granting-access/index) for the user identity, specifying `cloud_key` as the requested access method mode. Include the entrance IDs that the user should be able to unlock.

<CodeGroup>
  ```javascript JavaScript theme={null}
  const accessGrant = await seam.accessGrants.create({
    user_identity_id: '22222222-2222-2222-2222-222222222222',
    acs_entrance_ids: ['f74e4879-5991-4e2f-a368-888983dcfbfc'],
    requested_access_methods: [
      { mode: 'cloud_key' }
    ],
  })
  ```

  ```python Python theme={null}
  access_grant = seam.access_grants.create(
      user_identity_id="22222222-2222-2222-2222-222222222222",
      acs_entrance_ids=["f74e4879-5991-4e2f-a368-888983dcfbfc"],
      requested_access_methods=[{"mode": "cloud_key"}],
  )
  ```

  ```ruby Ruby theme={null}
  access_grant = seam.access_grants.create(
    user_identity_id: "22222222-2222-2222-2222-222222222222",
    acs_entrance_ids: ["f74e4879-5991-4e2f-a368-888983dcfbfc"],
    requested_access_methods: [{ mode: "cloud_key" }]
  )
  ```

  ```php PHP theme={null}
  $accessGrant = $seam->access_grants->create(
    user_identity_id: "22222222-2222-2222-2222-222222222222",
    acs_entrance_ids: ["f74e4879-5991-4e2f-a368-888983dcfbfc"],
    requested_access_methods: [["mode" => "cloud_key"]]
  );
  ```

  ```csharp C# theme={null}
  var accessGrant = seam.AccessGrants.Create(
    userIdentityId: "22222222-2222-2222-2222-222222222222",
    acsEntranceIds: new List<string>
    {
      "f74e4879-5991-4e2f-a368-888983dcfbfc"
    },
    requestedAccessMethods: new List<RequestedAccessMethod>
    {
      new RequestedAccessMethod { Mode = "cloud_key" }
    }
  );
  ```

  ```java Java theme={null}
  var accessGrant = seam.accessGrants().create(
    AccessGrantsCreateRequest.builder()
      .userIdentityId("22222222-2222-2222-2222-222222222222")
      .acsEntranceIds(List.of(
        "f74e4879-5991-4e2f-a368-888983dcfbfc"
      ))
      .requestedAccessMethods(List.of(
        RequestedAccessMethod.builder()
          .mode("cloud_key")
          .build()
      ))
      .build()
  );
  ```

  ```bash cURL theme={null}
  curl -X 'POST' \
    'https://connect.getseam.com/access_grants/create' \
    -H "Authorization: Bearer ${SEAM_API_KEY}" \
    -H 'Content-Type: application/json' \
    -d '{
    "user_identity_id": "22222222-2222-2222-2222-222222222222",
    "acs_entrance_ids": ["f74e4879-5991-4e2f-a368-888983dcfbfc"],
    "requested_access_methods": [{ "mode": "cloud_key" }]
  }'
  ```
</CodeGroup>

**Output:**

```json theme={null}
{
  "access_grant_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "user_identity_id": "22222222-2222-2222-2222-222222222222",
  "access_method_ids": ["99887766-5544-3322-1100-aabbccddeeff"],
  "requested_access_methods": [
    { "mode": "cloud_key" }
  ],
  ...
}
```

## Step 3: See Which Doors an Access Method Covers

An access method can cover multiple doors — for example, if the Access Grant includes several entrances or spaces. To see which doors a cloud key can unlock, call `/access_methods/get_related`.

<CodeGroup>
  ```javascript JavaScript theme={null}
  const related = await seam.accessMethods.getRelated({
    access_method_ids: [accessMethod.access_method_id],
  })

  console.log(related.acs_entrances) // entrances this cloud key can unlock
  ```

  ```python Python theme={null}
  related = seam.access_methods.get_related(
      access_method_ids=[access_method.access_method_id]
  )

  print(related.acs_entrances)  # entrances this cloud key can unlock
  ```

  ```ruby Ruby theme={null}
  related = seam.access_methods.get_related(
    access_method_ids: [access_method.access_method_id]
  )

  puts related.acs_entrances  # entrances this cloud key can unlock
  ```

  ```php PHP theme={null}
  $related = $seam->access_methods->get_related(
    access_method_ids: [$accessMethod->access_method_id]
  );

  echo json_encode($related->acs_entrances);  // entrances this cloud key can unlock
  ```

  ```csharp C# theme={null}
  var related = seam.AccessMethods.GetRelated(
    accessMethodIds: new List<string> { accessMethod.AccessMethodId }
  );

  // related.AcsEntrances — entrances this cloud key can unlock
  ```

  ```java Java theme={null}
  var related = seam.accessMethods().getRelated(
    AccessMethodsGetRelatedRequest.builder()
      .accessMethodIds(List.of(accessMethod.getAccessMethodId()))
      .build()
  );
  ```

  ```bash cURL theme={null}
  curl -X 'POST' \
    'https://connect.getseam.com/access_methods/get_related' \
    -H "Authorization: Bearer ${SEAM_API_KEY}" \
    -H 'Content-Type: application/json' \
    -d '{
    "access_method_ids": ["99887766-5544-3322-1100-aabbccddeeff"]
  }'
  ```
</CodeGroup>

## Step 4: Unlock the Entrance

Once the access grant is active, unlock the entrance on behalf of the user by calling `/access_methods/unlock_door` with the cloud key `access_method_id` and the `acs_entrance_id`. The endpoint resolves the credential internally and attributes the unlock to the user identity in the ACS audit trail.

<CodeGroup>
  ```javascript JavaScript theme={null}
  const actionAttempt = await seam.accessMethods.unlockDoor({
    access_method_id: '99887766-5544-3322-1100-aabbccddeeff',
    acs_entrance_id: 'f74e4879-5991-4e2f-a368-888983dcfbfc',
  })
  ```

  ```python Python theme={null}
  action_attempt = seam.access_methods.unlock_door(
      access_method_id="99887766-5544-3322-1100-aabbccddeeff",
      acs_entrance_id="f74e4879-5991-4e2f-a368-888983dcfbfc",
  )
  ```

  ```ruby Ruby theme={null}
  action_attempt = seam.access_methods.unlock_door(
    access_method_id: "99887766-5544-3322-1100-aabbccddeeff",
    acs_entrance_id: "f74e4879-5991-4e2f-a368-888983dcfbfc"
  )
  ```

  ```php PHP theme={null}
  $actionAttempt = $seam->access_methods->unlock_door(
    access_method_id: "99887766-5544-3322-1100-aabbccddeeff",
    acs_entrance_id: "f74e4879-5991-4e2f-a368-888983dcfbfc"
  );
  ```

  ```csharp C# theme={null}
  var actionAttempt = seam.AccessMethods.UnlockDoor(
    accessMethodId: "99887766-5544-3322-1100-aabbccddeeff",
    acsEntranceId: "f74e4879-5991-4e2f-a368-888983dcfbfc"
  );
  ```

  ```java Java theme={null}
  var actionAttempt = seam.accessMethods().unlockDoor(
    AccessMethodsUnlockDoorRequest.builder()
      .accessMethodId("99887766-5544-3322-1100-aabbccddeeff")
      .acsEntranceId("f74e4879-5991-4e2f-a368-888983dcfbfc")
      .build()
  );
  ```

  ```bash cURL theme={null}
  curl -X 'POST' \
    'https://connect.getseam.com/access_methods/unlock_door' \
    -H "Authorization: Bearer ${SEAM_API_KEY}" \
    -H 'Content-Type: application/json' \
    -d '{
    "access_method_id": "99887766-5544-3322-1100-aabbccddeeff",
    "acs_entrance_id": "f74e4879-5991-4e2f-a368-888983dcfbfc"
  }'
  ```
</CodeGroup>

**Output:**

```json theme={null}
{
  "action_attempt_id": "5f4e3d2c-1b0a-9f8e-7d6c-5b4a3c2d1e0f",
  "action_type": "UNLOCK_DOOR",
  "status": "success",
  "result": { "was_confirmed_by_device": false },
  "error": null
}
```

The unlock event appears in the ACS audit trail attributed to the specific user identity, not as a generic system action.

## Next Steps

* [Access Grants](/use-cases/granting-access/index) — Learn more about creating and managing Access Grants.
* [Access Methods API Reference](/api/access_methods/object) — See all access method properties and endpoints.
