Initialize the home

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() to create a Home object. This is a basic step to access a user's home:

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:

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 for more information.
  • sharedAppGroup: The App Group used for shared storage with the Google Home Matter Commissioning SDK.

  • 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.

  • 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:

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 entity, which is distinct from HomeDevice. To interact with device groups, include the relevant device types and traits when configuring ReferencedAutomationTypes in Home.configure, along with the GroupTrait, GroupManagementTrait, and GroupMembershipTrait traits.

For more information, see 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.
// 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():

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:

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:

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():

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():

  • structureID — The specific structure ID to pre-select in the permission dialog. Get this by checking the 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:

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:) method. The structure ID must be known from a prior mapping on the partner side.

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:

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 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() to disconnect the Home object from the account:

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

Users can revoke previously-granted access:

  1. Through Google Account settings > 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 to export their Google Home data and to their Google Account settings 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 is delivered to your cloud backend. Refer to 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.