Access APIs from within a module

To use the platform or machine APIs, you must authenticate using API keys.

Use platform APIs from a module

The following steps show you how to use the following APIs from a module:

  1. Add the following imports and the create_viam_client_from_module method:

    import os
    from viam.rpc.dial import DialOptions, Credentials
    from viam.app.viam_client import ViamClient
    from viam.app.app_client import AppClient
    from viam.app.data_client import DataClient
    from viam.app.ml_training_client import MLTrainingClient
    from viam.app.billing_client import BillingClient
    
    async def create_viam_client_from_module():
        # Get API credentials from module environment variables
        api_key = os.environ.get("VIAM_API_KEY")
        api_key_id = os.environ.get("VIAM_API_KEY_ID")
    
        if not api_key or not api_key_id:
            raise Exception("VIAM_API_KEY and VIAM_API_KEY_ID " +
                            "environment variables are required")
    
        # Create dial options with API key authentication
        dial_options = DialOptions(
            credentials=Credentials(
                type="api-key",
                payload=api_key,
            ),
            auth_entity=api_key_id
        )
    
        # Create ViamClient and get app_client
        viam_client = await ViamClient.create_from_dial_options(dial_options)
    
        return viam_client
    
  2. Add the viam_client or other clients to the resource class:

    class TestSensor(Sensor, EasyResource):
        viam_client: Optional[ViamClient] = None
        app_client: Optional[AppClient] = None
        data_client: Optional[DataClient] = None
        ml_training_client: Optional[MLTrainingClient] = None
        billing_client: Optional[BillingClient] = None
    
        # ...
    
  3. Initialize the clients and use them:

    async def some_module_function(self):
       # Ensure there is only one viam_client connection
       if not self.viam_client:
           self.viam_client = await create_viam_client_from_module()
    
       self.app_client = self.viam_client.app_client
       self.data_client = self.viam_client.data_client
       self.ml_training_client = self.viam_client.ml_training_client
       self.billing_client = self.viam_client.billing_client
       # Use the clients in your module
       locations = await self.app_client.list_locations(os.environ.get("VIAM_PRIMARY_ORG_ID"))
    

The module environment variables VIAM_API_KEY and VIAM_API_KEY_ID provide machine owner access for the machine the module is running on.

If you need a higher level of access, you can pass API keys as part of the module configuration:

  1. Create an API key with the appropriate permissions from your organization settings page.

  2. Add the API key and API key ID values to the module configuration:

    {
      "modules": [
        {
          "type": "registry",
          "name": "example-module",
          "module_id": "naomi:example-module",
          "version": "latest",
          "env": {
            "VIAM_API_KEY": "abcdefg987654321abcdefghi",
            "VIAM_API_KEY_ID": "1234abcd-123a-987b-1234567890abc"
          }
        }
      ]
    }
    

    This changes the environment variables VIAM_API_KEY and VIAM_API_KEY_ID from the default to the provided ones.

Use the machine management API from a module

To use the machine management (robot_client) API, you must get the machine’s FQDN and API keys from the module environment variables.

  1. Add the following imports and the create_robot_client_from_module method:

    # Add imports
    import os
    from viam.robot.client import RobotClient
    
    # For robot client, you can also use the machine's FQDN:
    async def create_robot_client_from_module():
        # Get API credentials from module environment variables
        api_key = os.environ.get("VIAM_API_KEY")
        api_key_id = os.environ.get("VIAM_API_KEY_ID")
        machine_fqdn = os.environ.get("VIAM_MACHINE_FQDN")
    
        if not api_key or not api_key_id or not machine_fqdn:
            raise Exception("VIAM_API_KEY, VIAM_API_KEY_ID, and " +
                            "VIAM_MACHINE_FQDN " +
                            "environment variables are required")
    
        # Create robot client options with API key authentication
        opts = RobotClient.Options.with_api_key(
            api_key=api_key,
            api_key_id=api_key_id
        )
    
        # Create RobotClient using the machine's FQDN
        robot_client = await RobotClient.at_address(machine_fqdn, opts)
    
        return robot_client
    
  2. Add the robot_client or other clients to the resource class:

    class TestSensor(Sensor, EasyResource):
        robot_client: Optional[RobotClient] = None
        # ...
    
  3. Initialize the client and use it:

    async def some_module_function(self):
        # Ensure there is only one robot client
        if not self.robot_client:
            self.robot_client = await create_robot_client_from_module()
        # Use the robot client
        resources = [str(name) for name in self.robot_client.resource_names]
    

The module environment variables VIAM_API_KEY and VIAM_API_KEY_ID provide machine owner access for the machine the module is running on.

If you need a higher level of access to access other machines, you can pass API keys as part of the module configuration:

  1. Create an API key with the appropriate permissions from your organization settings page.

  2. Add the API key and API key ID values to the module configuration:

    {
      "modules": [
        {
          "type": "registry",
          "name": "example-module",
          "module_id": "naomi:example-module",
          "version": "latest",
          "env": {
            "VIAM_API_KEY": "abcdefg987654321abcdefghi",
            "VIAM_API_KEY_ID": "1234abcd-123a-987b-1234567890abc"
          }
        }
      ]
    }
    

    This changes the environment variables VIAM_API_KEY and VIAM_API_KEY_ID from the default to the provided ones.