Before using any of the Home APIs for iOS, you must initialize the home in your
app.

`Home` is the top-level entry to the SDK and provides access to all entities in
the user's structure.

When requesting all entities of a particular type, the API returns a `Query`
object that lets you choose how to receive the results.

## Create a Home object

Use [`connect()`](https://developers.home.google.com/reference/swift/GoogleHomeSDK/Classes/Home.md.txt#connect) to create
a `Home` object. This is a basic step to access a user's home:

```swift
do {
  self.home = try await Home.connect()
} catch {
  Logger.error("Auth error: \(error).")
}
```

This call prompts the SDK to check authorization state. If unauthenticated, the
SDK presents the OAuth flow for a user to grant permission to their home to the
app.

Once you have access to a home, you can use the following APIs:

- [Device](https://developers.home.google.com/apis/ios/device.md.txt) \& [Structure](https://developers.home.google.com/apis/ios/structure.md.txt) APIs
- [Commissioning API](https://developers.home.google.com/apis/ios/commissioning.md.txt)

## Home configuration

When initialized, the `Home` client reads from an app provided
`HomeClientConfiguration` object to prepare its environment. This object should
be passed to the client prior to any Home API calls so that the permissions,
automations, and commissioning features are able to interact with one's smart
home project.

- `teamID`: The Apple Team ID of the app using SDK.
- `clientID`: The OAuth Client ID of the app using SDK. See [Set up OAuth for
  your iOS app](https://developers.home.google.com/apis/ios/oauth) for more information.
- `sharedAppGroup`: The App Group used for shared storage with the Google Home
  Matter Commissioning SDK.

  > [!NOTE]
  > **Note:** This must match the value used by the Google Home Matter Commissioning SDK. It must be registered in the entitlements for both the app and the Matter Commissioning App extension.

- `strictOperationValidation`: Validates if a trait or command is supported.

  - If `true`, you will receive an exception message if your trait or command is unsupported.
  - If `false`, a command or attribute write will still be sent, but you will receive an error for the unsupported trait.
- `referencedAutomationTypes`: The list of traits and device types you intend to
  use with the [Automation API](https://developers.home.google.com/apis/ios/automation.md.txt).

- `locale`: The optional `Locale` used for SDK WebViews and persisted user
  language settings.

These options are set using the `configure()` method of the `Home`
object as shown:

```swift
Home.configure {
  // Authentication and Home API usage configurations
  $0.teamID = "ABC123"
  $0.clientID = "123-abc.apps.googleusercontent.com"
  $0.strictOperationValidation = true
  $0.locale = Locale(identifier: "en-US")
  // Commissioning configurations
  $0.sharedAppGroup = "group.com.company.commissioning"
  // Automation configurations
  $0.referencedAutomationTypes = ReferencedAutomationTypes(
    deviceTypes: [
        OnOffLightDeviceType.self,
        TemperatureSensorDeviceType.self,
        WindowCoveringDeviceType.self,
    ],
    traits: [
        Google.TimeTrait.self,
        Matter.OnOffTrait.self,
        Matter.TemperatureMeasurementTrait.self,
        Matter.WindowCoveringTrait.self,
    ]
  )
}
```
Device groups are represented by the [`DeviceGroup`](https://developers.home.google.com/reference/swift/GoogleHomeSDK/Structs/DeviceGroup.md.txt) entity, which is distinct from [`HomeDevice`](https://developers.home.google.com/reference/swift/GoogleHomeSDK/Structs/HomeDevice.md.txt). To interact with device groups, include the relevant device types and traits when configuring [`ReferencedAutomationTypes`](https://developers.home.google.com/reference/swift/GoogleHomeSDK/Classes/ReferencedAutomationTypes.md.txt) in `Home.configure`, along with the [`GroupTrait`](https://developers.home.google.com/reference/swift/GoogleHomeTypes/Enums/Google/GroupTrait), [`GroupManagementTrait`](https://developers.home.google.com/reference/swift/GoogleHomeTypes/Enums/Google/GroupManagementTrait.md.txt), and [`GroupMembershipTrait`](https://developers.home.google.com/reference/swift/GoogleHomeTypes/Enums/Google/GroupMembershipTrait.md.txt) traits.

For more information, see [Device groups](https://developers.home.google.com/apis/ios/structure.md.txt#device-groups).

### Configure the app locale

In addition to setting an initial locale in `Home.configure`, you can update or
read the active `Locale` at runtime using `Home.setLocale(_:)` and
`Home.getLocale()`.

When a locale is configured, the SDK passes the corresponding BCP-47 language
tag to SDK-launched WebViews, including the permissions consent and device
removal flows. If no locale is set, these WebViews default to English.

- Calling `Home.setLocale(_:)` before connecting to a structure updates the locale in memory so that initial OAuth and permissions WebViews use it. Once a session connects, the SDK syncs the locale with the cloud.
- Calling `Home.setLocale(_:)` during an active session updates the locale in memory and persists the BCP-47 identifier to the cloud for that user and app. If the cloud update fails, `Home.setLocale(_:)` throws an error and reverts the local in-memory locale to its previous value.

```swift
// Update the app locale at runtime
do {
  try await Home.setLocale(Locale(identifier: "en-US"))
} catch {
  Logger.error("Failed to set locale: \(error).")
}

// Read the configured locale, or nil if not set
let currentLocale: Locale? = Home.getLocale()
```

## Permissions

Before using any of the Home APIs for iOS, the app must have permission to
access devices or structures. The `connect()` process will prompt the SDK to
check authorization state, and if unauthorized, will present the OAuth flow for
granting permission.

### Check permissions

To check if permissions to the Home APIs have previously been granted by the
user, use
[`Home.restoreSession()`](https://developers.home.google.com/reference/swift/GoogleHomeSDK/Classes/Home.md.txt#restoresession):

```swift
self.home = await Home.restoreSession()
```

If there are no active users that have granted permissions, you will
receive `nil`. To request permissions, use the `connect()` process to prompt the
OAuth flow.

To check if you have a valid client, use the following:

```swift
guard let home = await Home.restoreSession() else {
  // No previous session existed.
  return.
}
self.home = home
```

#### Check if past permission is still valid

To check if previous granted permission is still valid, use the following:

```swift
func checkPermissions() async -> Home? {
  guard let home = await Home.restoreSession() else {
    // No previous session.
    return nil
  }

  do {
    // Check if operations can be executed.
    _ = try await home.structures().list()
    // If this doesn't throw, it means that the session is valid.
    return home
  } catch {
    // If this throws a HomeError.permissionDenied it means that the session is no longer valid.
    return nil
  }
}
```

If your app previously granted permissions, but the permissions were revoked
while the app was not running, you will receive a `permissionDenied` error code.

### Update permissions

To update permissions granted to the Home APIs, use
[`presentPermissionsUpdate()`](https://developers.home.google.com/reference/swift/GoogleHomeSDK/Classes/Home.md.txt#presentpermissionsupdate):

```swift
self.home?.permissions.presentPermissionsUpdate()
```

If the active user is signed into Safari, the permissions view will be presented
for that user. Otherwise, the user will be prompted to select an account or sign
in.

### Update permissions with structure hinting

Structure hinting allows an app to pre-select a specific structure, or restrict
the list of available structures, when requesting an incremental change to the
user's Home APIs permissions. By passing structure parameters into the
authorization request, the permissions dialog will automatically focus on the
chosen structure, reducing user friction and preventing configuration errors.

Structure hinting is managed using the following optional configuration
parameters for
[`presentPermissionsUpdate()`](https://developers.home.google.com/reference/swift/GoogleHomeSDK/Structs/UserScopedPermissionsController.md.txt#presentpermissionsupdatestructureid:allowedstructureids:allowstructurechange:):

- `structureID` --- The specific structure ID to pre-select in the permission dialog. Get this by checking the [structure
  properties](https://developers.home.google.com/apis/ios/structure#properties) for the structure being updated.
- `allowedStructureIDs` --- A list of structure IDs. If provided, the permission dialog will filter the available structures to only show those in this list. This can be left unspecified in most cases, unless you want to ensure the user stays within an already-granted list of structures.
- `allowStructureChange` --- Determines whether the user is permitted to change the pre-selected structure or select outside the allowed list.

Add these parameters to the `presentPermissionsUpdate()` call:

```swift
let targetStructureID = "target-structure-id"

// Launch the permissions view
try await self.home?.permissions.presentPermissionsUpdate(
    structureID: targetStructureID,
    allowStructureChange: true
)
```

The user will be presented with the consent screen already filtered to the
structure noted in the `structureID` parameter.

### Structure hint when the user is not logged in

If the user is not logged into the app, but you want to use structure hinting,
use the
[`migrating(structureID:)`](https://developers.home.google.com/reference/swift/GoogleHomeSDK/Classes/Home.md.txt#migratingstructureid:)
method. The structure ID must be known from a prior mapping on the partner side.

> [!NOTE]
> **Note:** This is a special use case for partners migrating users to the Home APIs. If you aren't doing this, use `presentPermissionsUpdate()` instead.

```swift
let targetStructureID = "target-structure-id"

// Structure hint if the user is not logged in and the structure ID is known
await migrating(
    structureID: targetStructureID
)
```

#### Allow user to switch structures with structure hinting

If a user has multiple structures in an app and you want to pre-select one while
still allowing them to switch between their available structures, enable
structure changes with the `allowStructureChange` parameter and provide a list
of structures in `allowedStructureIds`:

```swift
let targetStructureID = "target-structure-id"
let allowedIDs = ["target-structure-id",
    "another-structure-id"]

// Launch the permissions view
try await self.home?.permissions.presentPermissionsUpdate(
    structureID: targetStructureID,
    allowedStructureIDs: allowedIDs,
    allowStructureChange: true
)
```

### OkGoogle permissions

The
[`okGoogle`](https://developers.home.google.com/reference/swift/GoogleHomeTypes/Enums/Google/AssistantFulfillmentTrait.md.txt#okgooglequery:)
command is a device-level command and can be used to automate any device in
the structure. However, a Home APIs app may not have access to every device.
The following table describes how permissions are enforced in such cases.

| Automation | Trait | Permissions enforcement |
|:---:|:---:|:---:|
| At 10:00pm, broadcast "Bedtime" on bedroom speaker. | ` AssistantBroadcastTrait ` on device. | **Automation creation** : - The broadcast device must be an Assistant device. - The app and user must have access to the device on which the broadcast occurs. **Automation execution** : - The app and user must have access to the device on which the broadcast occurs. |
| At 10:00pm, broadcast "Bedtime" on all devices | ` AssistantBroadcastTrait ` on structure. | **Automation creation** : - There must be at least one Assistant device in the structure that the app and user have access to. - The app and user must have access to the structure. **Automation execution** : - The app and user must have access to the structure. |
| At 10:00pm, "play some music" | ` AssistantFulfillmentTrait.OkGoogleCommand ` | **Automation creation** : - The app and user must have access to the devices to which the automation issues commands. **Automation execution** : - The app and user must have access to the devices to which the automation issues commands. |
| Whenever someone says "play some music" | ` VoiceStarterTrait.OkGoogleEvent ` | **Automation creation** : - The app and user must have access to the structure. An Automation doesn't require an Assistant device to pass validation or to run, because any user with access to the structure may use their phone (using the same Google Account) to engage with Assistant and trigger the VoiceStarter. **Automation execution** : - The app doesn't require permission to access the device which starts the automation. - The app and user must have permission to access the device on which the action occurs. |

## Revoke access

To clear client side access, use
[`disconnect()`](https://developers.home.google.com/reference/swift/GoogleHomeSDK/Classes/Home.md.txt#disconnect)
to disconnect the `Home` object from the account:

```swift
await self.home?.disconnect()
self.home = nil
```

> [!NOTE]
> **Note:** This won't revoke the OAuth access granted when as a result of completing the permissions flow.

Users can revoke previously-granted access:

1. Through [Google Account
   settings](https://myaccount.google.com/)
   **\> Data \& privacy \> Third-party apps \& services**. This will revoke the
   OAuth token that was issued when initial consent was granted, and
   will revoke access to any instance of the app that the user was using across
   all surfaces (phones) and structures.

   The user may be directed with a deep link to the **Third-party apps \&
   services** sub-page using the following URL scheme:

       https://myaccount.google.com/connections/link?project_number=Cloud project_number

2. Through the **Google Home app (GHA) \> Settings \> Linked Apps** page.
   Clicking on in the
   GHA will take you to
   the **Settings** page. From there, click the **Linked Apps** tile which
   takes you to a page that looks similar to the consent screen. From this page
   the user can remove access to the app. The user can use this same page to
   change which device types or specific sensitive devices are accessible to the
   app.

### User data deletion and export

The platform automatically manages backend data deletion when a user deletes
their Google Account or leaves a structure:

- If the deleted user is the sole owner of a structure, the platform deletes the structure and its device associations.
- If other owners remain in a shared structure, the structure and its shared devices persist for the remaining members. The platform removes the departed user's membership and unlinks any third-party Cloud-to-cloud devices connected solely through that user's credentials.
- Account deletion immediately and permanently removes the user's structure data and application permissions. Even if the user later recovers their Google Account, their structures and permissions are not restored.

The Home APIs do not provide endpoints to export or delete a user's Google
Account data. Direct users with a Google Account to
[Google Takeout](https://takeout.google.com/) to
export their Google Home data and to their [Google Account
settings](https://myaccount.google.com/) to manage
account deletion.

## Guidance if user revokes full permissions

If the user revokes full permissions, all existing automations will
stop working. Also, if the user revokes access to specific devices, then
starters, conditions, and actions associated with those devices will
stop working.

**Each time the app starts, be sure to check that the permissions
are still in effect. If they have been revoked, then be sure that all previous
data are removed, including any data cached in the application.**

When structure access is revoked, a
[`StructureAccessRevokedEvent`](https://developers.home.google.com/partners/services/camera/cloud-events#structure_grants)
is delivered to your cloud backend. Refer to
[Structure grants](https://developers.home.google.com/partners/services/camera/cloud-events#structure_grants) for
the end-to-end partner cloud and mobile app revocation workflow.

## App-initiated Google sign-in

On iOS, the SDK combines authorization with Apple's DeviceCheck API to prevent a
malicious app from exfiltrating the user's SDK access token. This is why you
cannot directly request the Home APIs scope outside of the SDK.

Unlike Android apps, iOS apps can use Google Account authentication without
requiring any explicit coding to do so. When the SDK recognizes a user is
signed-in with Google Sign-In, it uses that Google Account when requesting the
Home APIs scope.