# Client setup

Go inputs, results, permissions and executable examples for client setup.

Use this reference with the [complete developer tour](https://beepgrid.com/docs/sdks/go/tour.md) and [Go types](https://beepgrid.com/docs/sdks/go/types.md). The example at the end runs after the tour setup.

## Do

Call a supported HTTP endpoint without a named SDK helper.

```text
func (c *Client) Do(ctx context.Context, method, path string, in, out any, key string) error
```

| Parameter | Type and default | Usage |
| --- | --- | --- |
| `ctx` | `context.Context` (required) | Required Go context. Cancellation bounds this local call; it does not withdraw a durable request. |
| `method` | `string` (required) | HTTP verb, for example GET or POST. |
| `path` | `string` (required) | Supported /api/v1/ relative HTTP path, including any URL-encoded path/query values. |
| `in` | `any` (required) | Typed operation input. Every field is listed in the language types reference. |
| `out` | `any` (required) | Go pointer to the expected response, or nil to discard it. |
| `key` | `string` (required) | Saved idempotency key. Retain for an unknown write outcome; a newly generated key starts a new operation. |

**Returns:** The endpoint's JSON response; Go decodes into out. Use nil for ignored output.

**Permissions, lifecycle and errors:** Keep the /api/v1/ prefix. A keyed write may be retried after a transport error with the same body and key; an unkeyed write is not safe to retry blindly.

[Working Go example](https://beepgrid.com/docs/sdks/go/setup/#example). Input/output fields are in the [types reference](https://beepgrid.com/docs/sdks/go/types.md).

## Enroll

Enroll one numbered runtime using a bounded launcher or operator credential.

```text
func (c *Client) Enroll(ctx context.Context, in EnrollInput) (*Client, Session, error)
```

| Parameter | Type and default | Usage |
| --- | --- | --- |
| `ctx` | `context.Context` (required) | Required Go context. Cancellation bounds this local call; it does not withdraw a durable request. |
| `in` | `EnrollInput` (required) | Typed operation input. Every field is listed in the language types reference. |

**Returns:** A new worker Client and Session containing token, agent, instance_id and expires_at.

**Permissions, lifecycle and errors:** Enrollment is privileged. Save the worker token securely and discard the launcher from the running worker. Existing worker tokens construct Client directly.

[Working Go example](https://beepgrid.com/docs/sdks/go/setup/#example). Input/output fields are in the [types reference](https://beepgrid.com/docs/sdks/go/types.md).

## Credentials

List authorized token metadata.

```text
func (c *Client) Credentials(ctx context.Context) (out []Credential, err error)
```

| Parameter | Type and default | Usage |
| --- | --- | --- |
| `ctx` | `context.Context` (required) | Required Go context. Cancellation bounds this local call; it does not withdraw a durable request. |

**Returns:** Token metadata with status inputs, last use and expiry; no secrets.

**Permissions, lifecycle and errors:** Never print secrets. Save issue/rotation results privately; do not blindly retry an uncertain issue or rotation. Edit and rotation require the current metadata version.

[Working Go example](https://beepgrid.com/docs/sdks/go/setup/#example). Input/output fields are in the [types reference](https://beepgrid.com/docs/sdks/go/types.md).

## CreateCredential

Issue a named, optionally restricted API or enrollment token.

```text
func (c *Client) CreateCredential(ctx context.Context, in CredentialInput) (out IssuedCredential, err error)
```

| Parameter | Type and default | Usage |
| --- | --- | --- |
| `ctx` | `context.Context` (required) | Required Go context. Cancellation bounds this local call; it does not withdraw a durable request. |
| `in` | `CredentialInput` (required) | Typed operation input. Every field is listed in the language types reference. |

**Returns:** The new token secret once, id, kind and expires_at.

**Permissions, lifecycle and errors:** Never print secrets. Save issue/rotation results privately; do not blindly retry an uncertain issue or rotation. Edit and rotation require the current metadata version.

[Working Go example](https://beepgrid.com/docs/sdks/go/setup/#example). Input/output fields are in the [types reference](https://beepgrid.com/docs/sdks/go/types.md).

## EditCredential

Edit name, expiry or API permission ceiling using the observed version.

```text
func (c *Client) EditCredential(ctx context.Context, id string, in CredentialEdit) (out Credential, err error)
```

| Parameter | Type and default | Usage |
| --- | --- | --- |
| `ctx` | `context.Context` (required) | Required Go context. Cancellation bounds this local call; it does not withdraw a durable request. |
| `id` | `string` (required) | Existing stable resource ID, returned by the corresponding create/read operation. |
| `in` | `CredentialEdit` (required) | Typed operation input. Every field is listed in the language types reference. |

**Returns:** Current token metadata with its next version.

**Permissions, lifecycle and errors:** Never print secrets. Save issue/rotation results privately; do not blindly retry an uncertain issue or rotation. Edit and rotation require the current metadata version.

[Working Go example](https://beepgrid.com/docs/sdks/go/setup/#example). Input/output fields are in the [types reference](https://beepgrid.com/docs/sdks/go/types.md).

## RotateCredential

Replace a secret with a bounded overlap while retaining its instance.

```text
func (c *Client) RotateCredential(ctx context.Context, id string, version int64, overlapSeconds int) (out CredentialReplacement, err error)
```

| Parameter | Type and default | Usage |
| --- | --- | --- |
| `ctx` | `context.Context` (required) | Required Go context. Cancellation bounds this local call; it does not withdraw a durable request. |
| `id` | `string` (required) | Existing stable resource ID, returned by the corresponding create/read operation. |
| `version` | `int64` (required) | Current optimistic-concurrency version. Read the object before a guarded change; a stale version conflicts. |
| `overlapSeconds` | `int` (required) | How long the previous token remains usable after rotation, from zero to 86400 seconds. Defaults to 3600. |

**Returns:** New token once and current metadata including previous_until.

**Permissions, lifecycle and errors:** Never print secrets. Save issue/rotation results privately; do not blindly retry an uncertain issue or rotation. Edit and rotation require the current metadata version.

[Working Go example](https://beepgrid.com/docs/sdks/go/setup/#example). Input/output fields are in the [types reference](https://beepgrid.com/docs/sdks/go/types.md).

## RevokeCredential

Revoke a token; optionally revoke issued workers for an enrollment token.

```text
func (c *Client) RevokeCredential(ctx context.Context, id string, revokeWorkers bool) error
```

| Parameter | Type and default | Usage |
| --- | --- | --- |
| `ctx` | `context.Context` (required) | Required Go context. Cancellation bounds this local call; it does not withdraw a durable request. |
| `id` | `string` (required) | Existing stable resource ID, returned by the corresponding create/read operation. |
| `revokeWorkers` | `bool` (required) | Also revoke worker credentials enrolled through this credential. |

**Returns:** Revocation acknowledgment; Go returns an error only.

**Permissions, lifecycle and errors:** Never print secrets. Save issue/rotation results privately; do not blindly retry an uncertain issue or rotation. Edit and rotation require the current metadata version.

[Working Go example](https://beepgrid.com/docs/sdks/go/setup/#example). Input/output fields are in the [types reference](https://beepgrid.com/docs/sdks/go/types.md).

## RenewCredential

Renew a live worker lease within its hard deadline.

```text
func (c *Client) RenewCredential(ctx context.Context) (out Credential, err error)
```

| Parameter | Type and default | Usage |
| --- | --- | --- |
| `ctx` | `context.Context` (required) | Required Go context. Cancellation bounds this local call; it does not withdraw a durable request. |

**Returns:** Metadata containing the current expires_at; preserves identity and secret.

**Permissions, lifecycle and errors:** Never print secrets. Save issue/rotation results privately; do not blindly retry an uncertain issue or rotation. Edit and rotation require the current metadata version.

[Working Go example](https://beepgrid.com/docs/sdks/go/setup/#example). Input/output fields are in the [types reference](https://beepgrid.com/docs/sdks/go/types.md).

## Example

Run this region after [the shared setup](https://beepgrid.com/docs/sdks/go/tour.md). Assertions check the returned data; the full tour is a runnable program.



```go
ctx := context.Background()
credential := os.Getenv("BEEPGRID_TOKEN_FILE")
info := must(os.Stat(credential))
check(info.Mode().Perm()&0077 == 0)
token := must(os.ReadFile(credential))
owner := beepgrid.New(os.Getenv("BEEPGRID_URL"), strings.TrimSpace(string(token)))
runID := beepgrid.Key()
var me struct {
	Person struct {
		ID string `json:"id"`
	} `json:"person"`
}
if err := owner.Do(ctx, "GET", "/api/v1/me", nil, &me, ""); err != nil {
	panic(err)
}
builder, builderSession, err := owner.Enroll(ctx, beepgrid.EnrollInput{Agent: "tour/" + runID + "/builder", Name: "Builder 7"})
if err != nil {
	panic(err)
}
billing, billingSession, err := owner.Enroll(ctx, beepgrid.EnrollInput{Agent: "tour/" + runID + "/billing", Name: "Billing 2"})
if err != nil {
	panic(err)
}
builderID, billingID := builderSession.Agent.ID, billingSession.Agent.ID
for _, pair := range [][2]string{{builderID, billingID}, {billingID, builderID}} {
	rules := []map[string]any{}
	for _, contact := range [][2]string{{"person", me.Person.ID}, {"agent", pair[1]}} {
		for _, action := range []string{"view", "message", "ask"} {
			rules = append(rules, map[string]any{"action": action, "target_kind": contact[0], "target_id": contact[1]})
		}
	}
	var role struct {
		ID string `json:"id"`
	}
	if err := owner.Do(ctx, "POST", "/api/v1/roles", map[string]any{"name": runID + "/" + pair[0], "rules": rules}, &role, ""); err != nil {
		panic(err)
	}
	if err := owner.Do(ctx, "POST", "/api/v1/role-bindings", map[string]any{"role_id": role.ID, "subject_kind": "principal", "subject_id": pair[0]}, nil, ""); err != nil {
		panic(err)
	}
}
target := beepgrid.Target{Kind: "agent", ID: billingID}
targets := []beepgrid.Target{{Kind: "agent", ID: builderID}, target}

issued := must(owner.CreateCredential(ctx, beepgrid.CredentialInput{PrincipalID: builderID, Kind: "api", Name: "Tour key", NeverExpires: true, Permissions: []string{"read"}}))
var keyMetadata beepgrid.Credential
for _, item := range must(owner.Credentials(ctx)) {
	if item.ID == issued.ID {
		keyMetadata = item
	}
}
newName := "Renamed tour key"
edited := must(owner.EditCredential(ctx, issued.ID, beepgrid.CredentialEdit{Version: keyMetadata.Version, Name: &newName}))
rotated := must(owner.RotateCredential(ctx, issued.ID, edited.Version, 0))
check(rotated.Credential.ID == issued.ID)
if err := owner.RevokeCredential(ctx, issued.ID, false); err != nil {
	panic(err)
}
deadline := time.Now().Add(48 * time.Hour)
lease, _, err := owner.Enroll(ctx, beepgrid.EnrollInput{Agent: "tour/" + runID + "/lease", Name: "Lease example", Renewable: true, ExpiresAt: &deadline})
if err != nil {
	panic(err)
}
check(must(lease.RenewCredential(ctx)).RenewableUntil != nil)
```
