Skip to content

Document authenticating a laptop script with API key environment variables or viam.json - #5479

Open
Jeremy Rose (jeremyrose-viam) wants to merge 5 commits into
viamrobotics:mainfrom
jeremyrose-viam:api-keys-for-scripts
Open

Jeremy Rose (jeremyrose-viam) wants to merge 5 commits into
viamrobotics:mainfrom
jeremyrose-viam:api-keys-for-scripts

Conversation

@jeremyrose-viam

@jeremyrose-viam Jeremy Rose (jeremyrose-viam) commented Oct 29, 2026 •

Copy link
Copy Markdown
Member

Adds a "Script on your laptop" section to Manage API keys, under "Use an API key".

It covers:

  • What a script needs to connect: machine address, API key, and API key ID (found on the machine's CONNECT tab, or created as described on the page).
  • Passing the key and key ID through VIAM_API_KEY and VIAM_API_KEY_ID, with a Python example that reads them and calls RobotClient.Options.with_api_key.
  • A viam.json alternative: how to copy the file from the app, and a Python example that reads the api_key block under cloud and authenticates with it. A short note covers files that have only a part secret, which the Python SDK can use as robot-secret credentials when connecting through the machine's cloud address. The default /etc/viam.json location is noted for computers where viam-agent is installed.
  • A security note: treat keys like passwords and keep them out of source control.

Verified against the Python SDK (viam-sdk 0.85.1, installed in a scratch venv):

  • The SDK reads VIAM_API_KEY and VIAM_API_KEY_ID itself only in ViamClient.create_from_env_vars(). RobotClient does not, so the script reads the variables.
  • robot-secret is a supported Credentials type for RobotClient dial options (and is rejected for ViamClient).

Verified against a real machine: a machine running in a cloud simulation, connected through its cloud address, with the credentials file copied from the app's Machine cloud credentials:

  • The api_key block in the file authenticates.
  • The part ID and secret as robot-secret credentials authenticate.
  • The same robot-secret call with a wrong secret is refused (permission denied), so the successful connections were real authentication.
  • The copied file contained the part ID, the secret, and an api_key block with a key ID and key.

Checks run locally: prettier 3.2.5, markdownlint, vale, scripts/frontmatter_rules.py, and make build-prod, all passing.

Not verified: connecting to a machine's local address with robot-secret credentials, other cloud environments, and the Go and TypeScript SDKs' handling of viam.json or environment variables. The examples are Python only.

🤖 Generated with Claude Code

@netlify

netlify Bot commented Oct 29, 2026 •

Copy link
Copy Markdown

✅ Deploy Preview for viam-docs ready!

Name Link
🔨 Latest commit c69ab6b
🔍 Latest deploy log https://app.netlify.com/projects/viam-docs/deploys/6ae8b8d16d99a4de06fd87f5
😎 Deploy Preview https://deploy-preview-5479--viam-docs.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.
Lighthouse
Lighthouse
1 paths audited
Performance: 32 (🔴 down 3 from production)
Accessibility: 100 (no change from production)
Best Practices: 100 (no change from production)
SEO: 92 (no change from production)
PWA: 60 (no change from production)
View the detailed breakdown and full score reports

To edit notification comments on pull requests, go to your Netlify project configuration.

@viambot viambot added the safe to build This pull request is marked safe to build from a trusted zone label Oct 29, 2026
@elizafarley

Eliza Farley (elizafarley) commented Oct 29, 2026 •

Copy link
Copy Markdown
Contributor

Docs review: Needs changes

Re-review at c69ab6b. The earlier blocker is resolved: the viam.json example now authenticates with the file's api_key block, the robot-secret path is a hedged one-line mention, and the author tested both against a real machine. The UUID/ValueError detail is gone too. One accuracy problem remains: the page says every viam.json has an api_key block, but the app adds that block only when a per-org feature flag is on, and the flag defaults to off.

CI: All required checks passing.

Docs health: No regressions.

Should fix

  • docs/organization/api-keys.md:282: "Each machine part has a viam.json file that holds ... an api_key block" is too strong. In viamrobotics/app api/config.go:93-111, genConnectionConfig adds api_key only when INCLUDE_API_KEY_IN_CONFIG is enabled for the part's org. That flag's FallbackValue is false (data/feature_models.go:316-319), and mask-cloud-creds.ts notes the field is "only present when FeatureIncludeAPIKeyInConfig is enabled". As written, this contradicts line 301, and readers whose file has no api_key get a KeyError from the example. Fix: Say the file holds the part ID and secret, and may include an api_key block. Then move the line 301 caveat up next to it, before the example.
  • docs/organization/api-keys.md:303: The "prefer a separate API key" advice comes right after the robot-secret sentence, so it reads as if it applies only to the secret. The api_key in viam.json is the machine's own default owner key (GetOrSetDefaultAPIKeyForRobot, api/config.go:95). Revoking it after a laptop leak affects the machine too, the same trade-off as the secret. Fix: Make clear the advice covers both credentials, for example: "Both credentials in viam.json belong to the machine itself. For a script on a laptop, prefer a separate API key scoped to the machine...".

Nits

  • docs/organization/api-keys.md:283: The Machine cloud credentials copy item appears only when hasWriteMachinePermissions is true (machine-status-dropdown.svelte:491-498). Fix: Add "(requires write access to the machine)" so Operator-role users know why they don't see it.
  • docs/organization/api-keys.md:300: On Windows, the agent installer reads C:\etc\viam.json (ui/src/lib/download.ts, getWindowsViamAgentInstallCommand). Fix: "at /etc/viam.json (C:\etc\viam.json on Windows)".

Needs owner sign-off

Claim Where Owning team Why unverified
Copied Machine cloud credentials normally include an api_key block docs/organization/api-keys.md:282-298 Fleet Gated by INCLUDE_API_KEY_IN_CONFIG (default off). Actual rollout across orgs isn't visible in code. If it's on for every org, the first should-fix becomes a wording nit.
robot-secret credentials work "when your script connects through the machine's cloud address" docs/organization/api-keys.md:302 Fleet The machine's own web server registers no robot-secret handler (rdk robot/web/web.go). The app accepts it as a legacy credential (server/dependencies/rpc_server.go), which fits the author's cloud-address test passing. Whether that path is supported going forward is an owner call.
Verified against source (8 claims)
  • ViamClient.create_from_env_vars() reads VIAM_API_KEY and VIAM_API_KEY_ID: viamrobotics/viam-python-sdk src/viam/app/viam_client.py:32-52
  • RobotClient doesn't read those variables itself (no os.environ use in robot/client.py or rpc/dial.py): viamrobotics/viam-python-sdk
  • RobotClient.Options.with_api_key(api_key, api_key_id) signature: viamrobotics/viam-python-sdk src/viam/robot/client.py:152
  • robot-secret is a valid Credentials.type, and ViamClient rejects it: viamrobotics/viam-python-sdk src/viam/rpc/dial.py:36, src/viam/app/viam_client.py:83-84
  • viam.json cloud fields id, secret, api_key.id, api_key.key: viamrobotics/rdk config/config.go:574,591-594; viamrobotics/app api/config.go:100-106
  • Machine cloud credentials copy item in the machine status menu: viamrobotics/app ui/src/routes/(auth-required)/machine/[machine_id]/machine-status-dropdown.svelte:498
  • CONNECT tab code sample fills in the machine address, API key, and key ID: viamrobotics/app .../connect/code-sample/code-sample-generate.ts:27-28,109-110
  • Default /etc/viam.json location: viamrobotics/rdk cli/app.go:4250,4268; viamrobotics/app ui/src/lib/download.ts (getCurlConfigCommand)

Automated review by Claude. Rerunning the review updates this comment.

@jeremyrose-viam

Copy link
Copy Markdown
Member Author

Thanks for the careful read. Pushed c69ab6b91.

Blocking: viam.json and robot-secret

I ran it against a real machine instead of reasoning from source. A machine running in a cloud simulation, connected through its cloud address, with the credentials file copied from Machine cloud credentials in the app:

  • The part ID and secret as robot-secret credentials connected.
  • The same call with a wrong secret was refused with permission denied, so the successful connection was real authentication, not a pass-through.
  • The api_key block in the same file also connected with with_api_key.

So the original example would have worked for cloud-dialed connections, but your points about the example still land, and I changed it:

  • The example now reads the api_key block, which is the supported credential type and the one the page already recommends.
  • The secret route is down to one sentence, scoped to connecting through the machine's cloud address, which is the only case I tested. I did not test connecting to a machine's local address with robot-secret, and the page doesn't claim it.
  • Files with only a part ID and secret (no api_key block) are called out, so nobody hits a KeyError on a missing field.

I kept the subsection, because the copied credentials file is what people get from the app, and the page now says how to read it.

Nits

  • CONNECT tab (line 253): leaving as is. The setup pages elsewhere on the site tell readers to open CONNECT and toggle Include API key on, which shows the machine's key, so the sentence is consistent with them. The "you won't see it again" note is about keys you create.
  • UUID and ValueError detail: cut.
  • Parallel sample to "SDK connection": leaving for now. The environment-variable version is the point of the section, and folding it in would bury it. Happy to revisit if you'd rather have one sample.

Local checks pass: prettier, markdownlint, vale, frontmatter, and make build-prod.

@viam-overwatch

viam-overwatch Bot commented Nov 5, 2026

Copy link
Copy Markdown

Hey Jeremy Rose (@jeremyrose-viam) — this PR has been approved and CI has been green for 3+ business days. Ready to merge?

Auto-comment from overwatch. Will not re-nudge for 7 days.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

safe to build This pull request is marked safe to build from a trusted zone

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants