Access platform 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:
- Fleet management (
app_client) - Data client (
data_client) - ML training (
ml_training_client) - Billing (
billing_client)
Add the following imports:
import os 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 BillingClientAdd the
viam_clientand 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 # ...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 ViamClient.create_from_env_vars() 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"))
Add the following imports:
"os" "go.viam.com/rdk/app"Add the
viam_clientand other clients to the resource class:type testPlatformApisGoModuleTestDataClient struct { resource.AlwaysRebuild name resource.Name logger logging.Logger cfg *Config cancelCtx context.Context cancelFunc func() viamClient *app.ViamClient appClient *app.AppClient dataClient *app.DataClient mlTrainingClient *app.MLTrainingClient billingClient *app.BillingClient }Initialize the clients and use them:
func (s *exampleModuleResource) SomeModuleFunction(ctx context.Context, extra map[string]interface{}) (map[string]interface{}, error) { if s.viamClient == nil { var err error s.viamClient, err = app.CreateViamClientFromEnvVars(ctx, &app.Options{}, s.logger) if err != nil { return nil, err } s.appClient = s.viamClient.AppClient() s.dataClient = s.viamClient.DataClient() s.mlTrainingClient = s.viamClient.MLTrainingClient() s.billingClient = s.viamClient.BillingClient() } locations, err := s.appClient.ListLocations(ctx, os.Getenv("VIAM_PRIMARY_ORG_ID")) if err != nil { return nil, err } // Use locations... return map[string]interface{}{"location_count": len(locations)}, nil }
Elevate access
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:
Create an API key with the appropriate permissions from your organization settings page.
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_KEYandVIAM_API_KEY_IDfrom 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.
Add the following imports and the
create_robot_client_from_modulemethod:# 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_clientAdd the
robot_clientor other clients to the resource class:class TestSensor(Sensor, EasyResource): robot_client: Optional[RobotClient] = None # ...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]
Add the following imports and the
createRobotClientFromModulefunction:"os" "go.viam.com/rdk/robot/client" "go.viam.com/utils/rpc" func createRobotClientFromModule(ctx context.Context, logger logging.Logger) (*client.RobotClient, error) { robotClient, err := client.New( ctx, os.Getenv("VIAM_MACHINE_FQDN"), logger, client.WithDialOptions(rpc.WithEntityCredentials( os.Getenv("VIAM_API_KEY_ID"), rpc.Credentials{ Type: rpc.CredentialsTypeAPIKey, Payload: os.Getenv("VIAM_API_KEY"), })), ) if err != nil { return nil, err } return robotClient, nil }Add the
viam_clientand other clients to the resource class:type testPlatformApisGoModuleTestDataClient struct { resource.AlwaysRebuild name resource.Name logger logging.Logger cfg *Config cancelCtx context.Context cancelFunc func() machine *client.RobotClient }Initialize the clients and use them:
func (s *exampleModuleResource) SomeModuleFunction(ctx context.Context, extra map[string]interface{}) (map[string]interface{}, error) {
if s.machine == nil {
var err error
s.machine, err = createRobotClientFromModule(ctx, s.logger)
if err != nil {
return nil, err
}
}
resources := s.machine.ResourceNames()
// Use resources...
return map[string]interface{}{"resource_count": len(resources)}, nil
}
To elevate access for the machine management API, follow the same steps described in Elevate access above.
Was this page helpful?
Glad to hear it! If you have any other feedback please let us know:
We're sorry about that. To help us improve, please tell us what we can do better:
Thank you!