---
title: "Go SDK — IAM & API keys"
description: "Authentication, API keys, and org membership with the Metalhost Go SDK."
url: "https://metalhost.net/docs/developers/guides/sdk-iam"
---

# Go SDK — IAM & API keys

`IamServiceClient` handles identity, API keys, and org membership. Most automation uses API keys — not user/password login.

## Caller identity

```
iam := iamv1connect.NewIamServiceClient(httpClient, base)
resp, err := iam.GetCallerIdentity(ctx, connect.NewRequest(
    &iamv1.GetCallerIdentityRequest{},
))
// resp.Msg — user email, org memberships, default project
```

Verify which orgs and projects your key can access.

## API keys

```
key, err := iam.CreateApiKey(ctx, connect.NewRequest(&iamv1.CreateApiKeyRequest{
    DisplayName:     "ci-deploy",
    DefaultProject:  "projects/my-app",
    ProjectScoped:   true, // hard-limit key to default_project
}))
secret := key.Msg.GetSecret() // shown once
prefix := key.Msg.GetApiKey().GetSecretPrefix()
```

| Scope | Behavior |
| --- | --- |
| Project-scoped | `projectScoped: true` + `defaultProject` — key cannot cross projects |
| Principal-wide | `projectScoped: false` — inherits caller's full org/project access |

```
iam.ListApiKeys(ctx, connect.NewRequest(&iamv1.ListApiKeysRequest{PageSize: 100}))
iam.RotateApiKey(ctx, connect.NewRequest(&iamv1.RotateApiKeyRequest{Name: keyName}))
iam.RevokeApiKey(ctx, connect.NewRequest(&iamv1.RevokeApiKeyRequest{Name: keyName}))
```

> **secret shown once**
>
> `CreateApiKey` and `RotateApiKey` return the full secret exactly once. Store it immediately — only the prefix appears in `ListApiKeys`.

## Org members

Roles: `ORG_ROLE_VIEWER`, `ORG_ROLE_EDITOR`, `ORG_ROLE_ADMIN`.

```
iam.InviteOrgMember(ctx, connect.NewRequest(&iamv1.InviteOrgMemberRequest{
    OrganizationName: "organizations/my-org",
    Email:            "dev@example.com",
    Role:             iamv1.OrgRole_ORG_ROLE_EDITOR,
}))
// Share invite link from response — no automated email
```

```
iam.ListOrgMembers(ctx, connect.NewRequest(&iamv1.ListOrgMembersRequest{
    OrganizationName: org,
}))
iam.UpdateOrgMemberRole(ctx, connect.NewRequest(&iamv1.UpdateOrgMemberRoleRequest{...}))
iam.RemoveOrgMember(ctx, connect.NewRequest(&iamv1.RemoveOrgMemberRequest{...}))
iam.ListPendingInvites / RevokeInvite
```

## Auth for SDK clients

Pass the API key via `metalhost.Config.APIKey` — see [Go SDK → Configure](https://metalhost.net/docs/developers/sdk.md#configure). User login RPCs (`Login`, `SignUp`, OIDC) are for the dashboard — not typical for server automation.

## What's next

- [Dashboard — API keys](https://metalhost.net/docs/dashboard/guides/api-keys.md)
- [Dashboard — Team members](https://metalhost.net/docs/dashboard/guides/members.md)
- [Concepts → Authentication](https://metalhost.net/docs/developers/concepts.md#auth)
