Browse topics
Credentials API
Securely store API keys and secrets for your custom applet.
The Credentials API provides secure key-value storage for secrets such as API keys, tokens, and passwords. Values are encrypted at rest using SQLCipher and are scoped by your applet’s manifest ID - each applet has its own isolated credential namespace.
Capability required: credentials:store
Frontend (iframe)
import { createResourceClient } from "@rightplace/sdk";
const rp = createResourceClient();
await rp.ready();
// Store an API key
await rp.credentials.set("openai_api_key", "sk-...");
// Retrieve it later
const apiKey = await rp.credentials.get("openai_api_key");
// → "sk-..."
// List stored credential keys (returns key names only, not values)
const keys = await rp.credentials.list();
// → ["openai_api_key"]
// Delete a credential
await rp.credentials.delete("openai_api_key");
Backend (Node.js)
The same API is available in backend methods via the rp host object:
import { createResourceServer } from "@rightplace/sdk/server";
const server = createResourceServer({
methods: {
saveApiKey: async (params, { rp }) => {
await rp.credentials.set("api_key", params.apiKey);
return { ok: true };
},
fetchData: async (_params, { rp }) => {
const apiKey = await rp.credentials.get("api_key");
if (!apiKey) throw new Error("API key not configured");
const res = await rp.http.request("https://api.example.com/data", {
headers: { Authorization: `Bearer ${apiKey}` },
});
return JSON.parse(res.body);
},
},
});
server.start();
MCP
Credentials are intentionally not exposed over MCP. Secrets never leave the owning applet - no agent tool can read, list, or enumerate stored credential keys or values.
If an agent needs to call an external API that requires a secret, route the call through an applet method that owns the credential (createResourceServer method -> rp.credentials.get -> outbound rp.http.request).
RobinPath Bridge
Also not exposed through rightplace.*. A RobinPath script that needs a secret should either:
-
Call the applet’s own method (which reads the credential internally), e.g.
rightplace.hook "res_abc" "fetchData" {query: "ping"} into $result -
Or, for ad-hoc scripts you own, use RobinPath environment variables (
robinpath_env_set,robinpath_env_list). These are stored in the RobinPath config, not the applet credential store.
API Reference
rp.credentials.get(key)
| Parameter | Type | Description |
|---|---|---|
key | string | The credential key to retrieve |
| Returns | Promise<string | null> | The value, or null if not found |
rp.credentials.set(key, value)
| Parameter | Type | Description |
|---|---|---|
key | string | The credential key to store |
value | string | The secret value to store |
| Returns | Promise<void> |
rp.credentials.delete(key)
| Parameter | Type | Description |
|---|---|---|
key | string | The credential key to delete |
| Returns | Promise<void> |
rp.credentials.list()
| Parameter | Type | Description |
|---|---|---|
| Returns | Promise<string[]> | Array of credential key names (not values) |
Manifest Configuration
{
"capabilities": [
"credentials:store"
]
}
Notes
- Values are encrypted at rest via SQLCipher. They are never exposed in logs.
list()returns key names only, never the secret values.- Credentials are scoped by manifest ID, not applet instance. All instances of the same applet type share the same credential store.
- Credentials persist across app restarts and applet updates.
- Use credentials for secrets (API keys, tokens, passwords). For non-sensitive data, use the Storage API instead.