> ## 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 Mobile Keys

> Learn how to create an Access Grant with a mobile key access method and deliver it through your mobile app using the Seam mobile SDKs.

Mobile keys let your users unlock doors by tapping a button in your mobile app. When you request a `mobile_key` access method in an Access Grant, Seam issues a mobile credential that you deliver through your own app using the Seam mobile SDKs. Each mobile key also includes an [Instant Key](/capability-guides/instant-keys/index) URL for immediate access without an app download.

Mobile keys work with:

* **Access control systems** — Salto KS, Salto Space, ASSA ABLOY Visionline and Vostio, dormakaba, Brivo, and other ACS platforms that support BLE-based mobile credentials. Specify entrances with `acs_entrance_ids` or use `space_ids`.

***

## Before You Begin

To use mobile keys, you need:

* A [Seam API key](https://console.seam.co)
* A connected ACS with BLE-capable lock hardware
* Mobile key licenses or subscriptions activated for your ACS (requirements vary by system — see your [system integration guide](/device-and-system-integration-guides#access-control-systems))
* A [user identity](/capability-guides/mobile-access/managing-mobile-app-user-accounts-with-user-identities) representing the person who will receive the mobile key
* An entrance that supports mobile keys (`can_unlock_with_mobile_key` is `true`)

<Info>
  If you plan to build a mobile app that delivers mobile keys, see [Mobile Access](/capability-guides/mobile-access/index) for the complete SDK integration guide. If you just want to share a link for instant access, see [Using Instant Keys](/use-cases/granting-access/using-instant-keys) instead.
</Info>

***

## Step 1: Verify Entrance Support

List the entrances for your ACS and confirm that `can_unlock_with_mobile_key` is `true`.

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

  const mobileKeyEntrances = entrances.filter(
    (e) => e.can_unlock_with_mobile_key
  )
  ```

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

  mobile_key_entrances = [
      e for e in entrances if e.can_unlock_with_mobile_key
  ]
  ```

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

  mobile_key_entrances = entrances.select do |e|
    e.can_unlock_with_mobile_key
  end
  ```

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

  $mobileKeyEntrances = array_filter(
    $entrances,
    fn($e) => $e->can_unlock_with_mobile_key
  );
  ```

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

  var mobileKeyEntrances = entrances
    .Where(e => e.CanUnlockWithMobileKey)
    .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>

***

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

Create an [Access Grant](/use-cases/granting-access/index) specifying `mobile_key` as the requested access method mode.

<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: 'mobile_key' }
    ],
    starts_at: '2025-07-13T15:00:00.000Z',
    ends_at: '2025-07-16T11:00:00.000Z',
  })
  ```

  ```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": "mobile_key"}],
      starts_at="2025-07-13T15:00:00.000Z",
      ends_at="2025-07-16T11:00:00.000Z",
  )
  ```

  ```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: "mobile_key" }],
    starts_at: "2025-07-13T15:00:00.000Z",
    ends_at: "2025-07-16T11:00:00.000Z"
  )
  ```

  ```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" => "mobile_key"]],
    starts_at: "2025-07-13T15:00:00.000Z",
    ends_at: "2025-07-16T11:00:00.000Z"
  );
  ```

  ```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 = "mobile_key" }
    },
    startsAt: "2025-07-13T15:00:00.000Z",
    endsAt: "2025-07-16T11:00:00.000Z"
  );
  ```

  ```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("mobile_key")
          .build()
      ))
      .startsAt("2025-07-13T15:00:00.000Z")
      .endsAt("2025-07-16T11:00:00.000Z")
      .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": "mobile_key" }],
    "starts_at": "2025-07-13T15:00:00.000Z",
    "ends_at": "2025-07-16T11:00:00.000Z"
  }'
  ```
</CodeGroup>

***

## Step 3: Deliver the Mobile Key

Once the access method is issued, list the access methods for the Access Grant to get the `client_session_id`. Use this value to initialize the Seam mobile SDK on your user's device so they can unlock doors from your app.

<CodeGroup>
  ```javascript JavaScript theme={null}
  const accessMethods = await seam.accessMethods.list({
    access_grant_id: accessGrant.access_grant_id,
  })

  const mobileKey = accessMethods[0]
  console.log(mobileKey.client_session_id)
  console.log(mobileKey.instant_key_url)
  ```

  ```python Python theme={null}
  access_methods = seam.access_methods.list(
      access_grant_id=access_grant.access_grant_id
  )

  mobile_key = access_methods[0]
  print(mobile_key.client_session_id)
  print(mobile_key.instant_key_url)
  ```

  ```ruby Ruby theme={null}
  access_methods = seam.access_methods.list(
    access_grant_id: access_grant.access_grant_id
  )

  mobile_key = access_methods[0]
  puts mobile_key.client_session_id
  puts mobile_key.instant_key_url
  ```

  ```php PHP theme={null}
  $accessMethods = $seam->access_methods->list(
    access_grant_id: $accessGrant->access_grant_id
  );

  $mobileKey = $accessMethods[0];
  echo $mobileKey->client_session_id;
  echo $mobileKey->instant_key_url;
  ```

  ```csharp C# theme={null}
  var accessMethods = seam.AccessMethods.List(
    accessGrantId: accessGrant.AccessGrantId
  );

  var mobileKey = accessMethods[0];
  Console.WriteLine(mobileKey.ClientSessionId);
  Console.WriteLine(mobileKey.InstantKeyUrl);
  ```

  ```java Java theme={null}
  var accessMethods = seam.accessMethods().list(
    AccessMethodsListRequest.builder()
      .accessGrantId(accessGrant.getAccessGrantId())
      .build()
  );
  ```

  ```bash cURL theme={null}
  curl -X 'POST' \
    'https://connect.getseam.com/access_methods/list' \
    -H "Authorization: Bearer ${SEAM_API_KEY}" \
    -H 'Content-Type: application/json' \
    -d '{
    "access_grant_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
  }'
  ```
</CodeGroup>

**Output:**

```json theme={null}
{
  "access_method_id": "6ba7b810-9dad-11d1-80b4-00c04fd430c8",
  "display_name": "Mobile Key",
  "mode": "mobile_key",
  "is_issued": true,
  "issued_at": "2025-06-16T16:55:03.924353Z",
  "client_session_id": "3f2504e0-4f89-11d3-9a0c-0305e82c3301",
  "instant_key_url": "https://ik.seam.co/ABCXYZ",
  ...
}
```

Use the `client_session_id` to look up the client session token, then pass it to the Seam mobile SDK to initialize your user's mobile app. For the complete mobile SDK integration guide, see [Mobile Access](/capability-guides/mobile-access/index).

<Info>
  Every mobile key also includes an `instant_key_url`. You can share this URL with your user as an alternative or backup access method — no app download required. See [Using Instant Keys](/use-cases/granting-access/using-instant-keys).
</Info>

***

## Step 4: See Which Doors the Mobile Key Covers

An access method can cover multiple doors — for example, if the Access Grant includes several entrances or spaces. To see which doors a mobile key unlocks, 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) // ACS entrances this mobile key unlocks
  ```

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

  print(related.acs_entrances)  # ACS entrances this mobile key unlocks
  ```

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

  puts related.acs_entrances  # ACS entrances this mobile key unlocks
  ```

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

  echo json_encode($related->acs_entrances);  // ACS entrances this mobile key unlocks
  ```

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

  // related.AcsEntrances — ACS entrances this mobile key unlocks
  ```

  ```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": ["f47ac10b-58cc-4372-a567-0e02b2c3d479"]
  }'
  ```
</CodeGroup>

***

## Next Steps

* [Mobile Access](/capability-guides/mobile-access/index) — Complete guide to building a mobile app with the Seam mobile SDKs.
* [Using Instant Keys](/use-cases/granting-access/using-instant-keys) — Share the Instant Key URL included with every mobile key.
* [Access Methods API Reference](/api/access_methods/object) — See all access method properties and endpoints.
