---
title: "Secrets · intentic sandbox API"
description: "Stored values the agent can use without ever reading them. Every route in the secrets group of the intentic sandbox API."
url: "https://intentic.dev/api/secrets/"
---

Connected systems

# Secrets

Stored values the agent can use without ever reading them

**On this page (12 sections)**

- [Store a secret](#secrets-set)
- [Names of the stored secrets](#secrets-list)
- [Make and store a random secret](#secrets-generate)
- [Delete a secret](#secrets-remove)
- [Every secret this sandbox holds, from everywhere](#secrets-inventory)
- [Show one secret's value](#secrets-reveal)
- [Which credentials need somebody's approval](#secrets-gates)
- [Put a credential behind named approvers](#secrets-setGate)
- [Stop requiring approval for a credential](#secrets-removeGate)
- [Which secrets are host-guarded, and where they may go](#secrets-hosts)
- [Turn a secret's host guard on or off, and set its hosts](#secrets-setHosts)
- [Ask a named person to release a credential](#secrets-request)

Write a secret, list which names exist, delete one. Revealing a value is the deliberate exception and the only route that hands one back; everywhere else the daemon substitutes a secret by reference at the moment a command runs.

12 calls. Pick one to open it, or use the list on the right.

**POST`/secrets` Store a secret**

Writes one name and value where the agent's references resolve it, without a restart: desired-state/.env once DevOps is active, the sandbox's own secret store before that.

### What you send

| Field | Type | Where |
| --- | --- | --- |
| `key` required The name to store it under,… | string | body |
| `value` required The value | string | body |

### What comes back

| Field | Type |
| --- | --- |
| `ok` Always true | true |

Try it answered in this tab

curl

```bash
curl -X POST "$SANDBOX/secrets" \
 -H "x-intentic-control: $INTENTIC_TOKEN" \
 -H "content-type: application/json" \
 -d '{"key":"OPENAI_API_KEY","value":"…"}'
```

TypeScript

```typescript
import { sandbox } from "@intentic/sandbox-client";

const result = await sandbox.secrets.set({
 "key": "OPENAI_API_KEY",
 "value": "…"
});
```

**GET`/secrets` Names of the stored secrets**

Which secrets exist here. Names only, never values.

### What you send

Nothing. Call it as it is.

### What comes back

| Field | Type |
| --- | --- |
| `keys` The names that exist here | string[] |

Try it answered in this tab

curl

```bash
curl "$SANDBOX/secrets" \
 -H "x-intentic-control: $INTENTIC_TOKEN"
```

TypeScript

```typescript
import { sandbox } from "@intentic/sandbox-client";

const result = await sandbox.secrets.list();
```

**POST`/secrets/generate` Make and store a random secret**

Makes a random value and stores it under a new name, where `set` would have put it, for a secret nobody has to find or paste (a session key, a signing secret, a password the task sets up itself). Answers the name and its length, never the value. Refused for a name something here already holds.

### What you send

| Field | Type | Where |
| --- | --- | --- |
| `key` required The name to store it under:… | string | body |
| `bytes` How much randomness, in bytes | integer | body |
| `format` How it is spelled: `hex` (0-9,… | "hex" | "base64url" | "alnum" | body |

### What comes back

| Field | Type |
| --- | --- |
| `key` The name it is stored under | string |
| `length` How many characters it is, which… | integer |
| `stored` Where it was kept: desired-state/.env once… | "env" | "sandbox" |

Try it answered in this tab

curl

```bash
curl -X POST "$SANDBOX/secrets/generate" \
 -H "x-intentic-control: $INTENTIC_TOKEN" \
 -H "content-type: application/json" \
 -d '{"key":"OPENAI_API_KEY","bytes":32,"format":"hex"}'
```

TypeScript

```typescript
import { sandbox } from "@intentic/sandbox-client";

const result = await sandbox.secrets.generate({
 "key": "OPENAI_API_KEY",
 "bytes": 32,
 "format": "hex"
});
```

**DELETE`/secrets/{key}` Delete a secret**

Removes one by name.

### What you send

| Field | Type | Where |
| --- | --- | --- |
| `key` required Which secret, by name | string | address |

### What comes back

| Field | Type |
| --- | --- |
| `ok` Always true | true |

Try it answered in this tab

curl

```bash
curl -X DELETE "$SANDBOX/secrets/OPENAI_API_KEY" \
 -H "x-intentic-control: $INTENTIC_TOKEN"
```

TypeScript

```typescript
import { sandbox } from "@intentic/sandbox-client";

const result = await sandbox.secrets.remove({
 "key": "OPENAI_API_KEY"
});
```

**GET`/secrets/inventory` Every secret this sandbox holds, from everywhere**

One view across all the places secrets live here: what exists, where it came from and whether it is working. Never any values. This one always answers, even before there is a store to write to.

### What you send

Nothing. Call it as it is.

### What comes back

| Field | Type |
| --- | --- |
| `entries` One entry per secret this sandbox… | object[] |
| `key` What identifies it | string |
| `kind` Where it came from: you set… | "env" | "generated" | "capability" | "provider" |
| `label` A friendlier name, for entries that… | string |
| `status` Whether it exists and, for a… | "missing" | "set" | "connected" |
| `requiredBy` What is waiting on it | object[] |
| `resourceId` Which resource | string |
| `type` What kind of resource it is | string |
| `storedAt` Where it actually lives, in words | string |
| `revealable` Whether its value can be shown… | boolean |
| `ci` Whether a copy has been given… | object |
| `synced` Whether the pipeline has it | boolean |
| `pushedAt` When it was last sent there | string |
| `lastUse` The last time an agent actually… | object |
| `at` When, in milliseconds | number |
| `lane` How it was used: a command,… | "shell" | "code" | "browser" |
| `detail` Where it went: the start of… | string |
| `approvedBy` Who released it for that use,… | string |
| `gate` Who has to release this before… | object |
| `approvers` Who may release it, by email | string[] |
| `scope` How far one release goes: `use`… | "use" | "conversation" |
| `hosts` Its host guard | object |
| `guard` Whether a use off the list,… | boolean |
| `list` The hosts it goes to unasked… | string[] |
| `source` Who set it: the owner, or… | "owner" | "connector" |

Try it answered in this tab

curl

```bash
curl "$SANDBOX/secrets/inventory" \
 -H "x-intentic-control: $INTENTIC_TOKEN"
```

TypeScript

```typescript
import { sandbox } from "@intentic/sandbox-client";

const result = await sandbox.secrets.inventory();
```

**POST`/secrets/reveal` Show one secret's value**

The only call that hands a value back, and it is for the owner alone. Sent as a body rather than in the address, so the name never ends up in a log or a browser's history.

### What you send

| Field | Type | Where |
| --- | --- | --- |
| `key` required Which secret, by name | string | body |

### What comes back

| Field | Type |
| --- | --- |
| `value` The value itself | string |

Try it answered in this tab

curl

```bash
curl -X POST "$SANDBOX/secrets/reveal" \
 -H "x-intentic-control: $INTENTIC_TOKEN" \
 -H "content-type: application/json" \
 -d '{"key":"OPENAI_API_KEY"}'
```

TypeScript

```typescript
import { sandbox } from "@intentic/sandbox-client";

const result = await sandbox.secrets.reveal({
 "key": "OPENAI_API_KEY"
});
```

**GET`/secrets/gates` Which credentials need somebody's approval**

What is gated and who may release it. Names and addresses only, never values, and the agent may read it too: knowing a credential needs Bob is what stops it concluding the account is simply not connected.

### What you send

Nothing. Call it as it is.

### What comes back

| Field | Type |
| --- | --- |
| `gates` Every gate in force | object[] |
| `subject` What is gated: a secret's name,… | string |
| `kind` Whether this gate covers one stored… | "secret" | "capability" |
| `approvers` Exactly who may release it, by… | string[] |
| `scope` How far one release goes: `use`… | "use" | "conversation" |

Try it answered in this tab

curl

```bash
curl "$SANDBOX/secrets/gates" \
 -H "x-intentic-control: $INTENTIC_TOKEN"
```

TypeScript

```typescript
import { sandbox } from "@intentic/sandbox-client";

const result = await sandbox.secrets.gates();
```

**PUT`/secrets/gates/{subject}` Put a credential behind named approvers**

Names exactly who may release one secret or one connected account, and how far a single release goes. The owner's call alone. A signed-in browser or a mounted server cannot be released for one use, so those are always for the rest of the conversation.

### What you send

| Field | Type | Where |
| --- | --- | --- |
| `subject` required What is gated: a secret's name,… | string | address |
| `kind` required Whether this gate covers one stored… | "secret" | "capability" | body |
| `approvers` required Exactly who may release it, by… | string[] | body |
| `scope` required How far one release goes: `use`… | "use" | "conversation" | body |

### What comes back

| Field | Type |
| --- | --- |
| `ok` Always true | true |

Try it answered in this tab

curl

```bash
curl -X PUT "$SANDBOX/secrets/gates/Fix%20the%20flaky%20parser%20test" \
 -H "x-intentic-control: $INTENTIC_TOKEN" \
 -H "content-type: application/json" \
 -d '{"kind":"secret","approvers":["…","…"],"scope":"use"}'
```

TypeScript

```typescript
import { sandbox } from "@intentic/sandbox-client";

const result = await sandbox.secrets.setGate({
 "subject": "Fix the flaky parser test",
 "kind": "secret",
 "approvers": [
 "…",
 "…"
 ],
 "scope": "use"
});
```

**DELETE`/secrets/gates/{subject}` Stop requiring approval for a credential**

Removes one gate, so the agent can use that credential the way it uses any other. The owner's call alone.

### What you send

| Field | Type | Where |
| --- | --- | --- |
| `subject` required Which gate, by the secret name… | string | address |

### What comes back

| Field | Type |
| --- | --- |
| `ok` Always true | true |

Try it answered in this tab

curl

```bash
curl -X DELETE "$SANDBOX/secrets/gates/Fix%20the%20flaky%20parser%20test" \
 -H "x-intentic-control: $INTENTIC_TOKEN"
```

TypeScript

```typescript
import { sandbox } from "@intentic/sandbox-client";

const result = await sandbox.secrets.removeGate({
 "subject": "Fix the flaky parser test"
});
```

**GET`/secrets/hosts` Which secrets are host-guarded, and where they may go**

Every secret and connected account whose host guard is set, on or off, and its hosts. With the guard on, a use aimed off the list, or anywhere a command's text does not show, asks a person first, whatever the safety judge says. Names and hosts only, never values.

### What you send

Nothing. Call it as it is.

### What comes back

| Field | Type |
| --- | --- |
| `guards` Every secret whose host guard has… | object[] |
| `subject` Which secret, by the name its… | string |
| `kind` Whether this gate covers one stored… | "secret" | "capability" |
| `guard` On: a use off the list,… | boolean |
| `hosts` Where it goes without asking while… | string[] |
| `source` Who set it: the owner, or… | "owner" | "connector" |

Try it answered in this tab

curl

```bash
curl "$SANDBOX/secrets/hosts" \
 -H "x-intentic-control: $INTENTIC_TOKEN"
```

TypeScript

```typescript
import { sandbox } from "@intentic/sandbox-client";

const result = await sandbox.secrets.hosts();
```

**PUT`/secrets/hosts/{subject}` Turn a secret's host guard on or off, and set its hosts**

Replaces one secret's host guard. Anybody who may use secrets can turn it on or take hosts away; turning it off or adding a host is the owner's: from the agent it raises a card for the owner in the live conversation and waits for their answer.

### What you send

| Field | Type | Where |
| --- | --- | --- |
| `subject` required Which secret, by name, or which… | string | address |
| `kind` Whether the subject is a secret… | "secret" | "capability" | body |
| `guard` required Whether a use off the list,… | boolean | body |
| `hosts` required The whole new list | string[] | body |
| `conversationId` Which conversation to ask the owner… | string | body |

### What comes back

| Field | Type |
| --- | --- |
| `guard` Whether the guard is on now | boolean |
| `hosts` Where it goes without asking while… | string[] |
| `approvedBy` Who approved the change, when it… | string |

Try it answered in this tab

curl

```bash
curl -X PUT "$SANDBOX/secrets/hosts/Fix%20the%20flaky%20parser%20test" \
 -H "x-intentic-control: $INTENTIC_TOKEN" \
 -H "content-type: application/json" \
 -d '{"kind":"secret","guard":true,"hosts":["sandbox-a1b2c3d4e5f6.intentic.dev","sandbox-a1b2c3d4e5f6.intentic.dev"],"conversationId":"nightly-changelog"}'
```

TypeScript

```typescript
import { sandbox } from "@intentic/sandbox-client";

const result = await sandbox.secrets.setHosts({
 "subject": "Fix the flaky parser test",
 "kind": "secret",
 "guard": true,
 "hosts": [
 "sandbox-a1b2c3d4e5f6.intentic.dev",
 "sandbox-a1b2c3d4e5f6.intentic.dev"
 ],
 "conversationId": "nightly-changelog"
});
```

**POST`/secrets/request` Ask a named person to release a credential**

Raises the release card in the live conversation and waits for one of the people named on it. Refused, rather than held, when there is nobody to ask: an unattended turn, no live conversation, or a click with no verified identity behind it.

### What you send

| Field | Type | Where |
| --- | --- | --- |
| `subject` required What to ask for: the secret's… | string | body |
| `why` One line on what it is… | string | body |
| `conversationId` Which conversation to raise the card… | string | body |

### What comes back

| Field | Type |
| --- | --- |
| `granted` Always true: a refusal is an… | true |
| `approvedBy` Who released it | string |
| `message` What the grant means in practice,… | string |

Try it answered in this tab

curl

```bash
curl -X POST "$SANDBOX/secrets/request" \
 -H "x-intentic-control: $INTENTIC_TOKEN" \
 -H "content-type: application/json" \
 -d '{"subject":"Fix the flaky parser test","why":"…","conversationId":"nightly-changelog"}'
```

TypeScript

```typescript
import { sandbox } from "@intentic/sandbox-client";

const result = await sandbox.secrets.request({
 "subject": "Fix the flaky parser test",
 "why": "…",
 "conversationId": "nightly-changelog"
});
```

More in Connected systems

[Previous ← Needs](https://intentic.dev/api/needs/)[Next VPN →](https://intentic.dev/api/vpn/)
