Skip to content

Secrets API

Store API keys in your Cloud project that your agents use without ever seeing them.

A secret is an API key or token your agents use without seeing it. You give Dexto the value once, with the exact hosts it may be sent to and how it is sent. After that, nothing returns it: not the API, not the agent, not its tools. A sandbox command gets a placeholder and Dexto puts the real value on its requests to those hosts; an MCP tool gets it attached by Dexto’s servers.

A secret belongs to your API key’s Cloud project. Use a developer API key, or the key Dexto gives a deployed Function or Site Worker as DEXTO_API_KEY. Every key of the project can create, change and delete its secrets; a secret of another project is 404. Every change is recorded in your organization’s audit log by name, never by value.

POST /v1/secrets
Terminal window
curl -X POST https://api.dexto.ai/v1/secrets \
-H "Authorization: Bearer $DEXTO_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "STRIPE_KEY",
"value": "sk_live_…",
"hosts": ["api.stripe.com"],
"placement": { "type": "bearer" }
}'
{
"object": "secret",
"id": "9b1e…",
"name": "STRIPE_KEY",
"hint": "…4242",
"hosts": ["api.stripe.com"],
"placement": { "type": "bearer" },
"created_by": { "type": "api_key", "api_key_id": "…" },
"last_used_at": null,
"created_at": "…",
"updated_at": "…"
}
FieldRules
name1–64 uppercase letters, digits and underscores, starting with a letter; unique in the project and fixed. Sandbox commands see it as an environment variable, so names the sandbox needs, such as PATH, are refused.
valueAt most 16 KiB, on one line. Stored encrypted and never returned.
hosts1–10 exact public hostnames reached over HTTPS, such as api.stripe.com. No IP addresses, ports, paths, localhost or wildcards.
placement{ "type": "bearer" } sends Authorization: Bearer <value>. { "type": "header", "name": "x-api-key", "prefix": "Token " } sends the value in that header, after the optional prefix.

hint shows the value’s last four characters when it has at least 20; otherwise it is null. A project holds at most 100 secrets. created_by is the API key that created the secret while it exists; otherwise the person, as { "type": "user", "user_id": "…" }, including when they used an OAuth token.

GET /v1/secrets
GET /v1/secrets/{secret_id}
PATCH /v1/secrets/{secret_id}
DELETE /v1/secrets/{secret_id}

Lists return a page at a time, newest first; pass next_after as after for the next page. PATCH replaces any of value, hosts and placement. The next request that uses the secret uses the change, so you rotate a key without changing any agent.

Deleting a secret that an active agent’s current version uses returns 409 and names the agents. Remove the secret from their tools, or archive them, first.

Name the secret in a sandbox tool’s secrets:

{
"type": "sandbox",
"sandbox": { "type": "session", "size": "large" },
"secrets": ["STRIPE_KEY"]
}

Each command the agent runs has $STRIPE_KEY set to a placeholder, so SDKs and scripts that read a key from the environment work unchanged. Requests the command makes over HTTPS to api.stripe.com go through Dexto, which replaces whatever credential the request carried with the real value as placement says, and removes the value from the response. Requests to any other host don’t get it: if a web page talks the agent into sending $STRIPE_KEY somewhere, only the placeholder leaves. A sandbox tool uses at most one secret per host, and a command’s access ends when the command does.

In a sandbox that several agents share, commands that use secrets take turns: a second one waits until the first ends (up to two and a half minutes, then it returns an error without running), so neither loses the other’s access. Commands without secrets don’t wait, and one running while another agent’s command holds a secret can reach that secret’s hosts with the value attached (it still can’t read it). Give an agent with secrets a session sandbox, or its own project sandbox, to keep its keys to itself.

Name the secret in an mcp tool’s auth; its hosts must include the server’s host:

{
"type": "mcp",
"name": "linear",
"server_url": "https://mcp.linear.app/mcp",
"auth": { "type": "secret", "secret": "LINEAR_KEY" },
"tools": ["create_issue"]
}

Dexto’s servers send the value with each request to that server only. See Agents for how MCP tools are saved, called and charged.

Storing secrets is free, and so is the brokered sandbox traffic. Each MCP tool call the server answers is charged a flat $0.001 from credits, toward the agent’s, project’s and key’s spend limits, like a Function call.

const dexto = createCapabilitiesClient({ apiKey: env.DEXTO_API_KEY });
const secret = await dexto.secrets.create({
name: "STRIPE_KEY",
value: env.STRIPE_KEY,
hosts: ["api.stripe.com"],
placement: { type: "bearer" },
});
await dexto.secrets.update(secret.id, { value: env.STRIPE_KEY_ROTATED });

dexto.secrets also has list, get and delete. See /v1/openapi.json for every schema and error.