Secrets Vault
Overview
The secret item type lets you collect credentials — passwords, API keys, hosting logins, third-party service tokens — from clients with encryption at rest. When your agent retrieves results with get_intake_results, the decrypted plaintext is returned once. After that first retrieval the value is gone — subsequent calls omit it.
Secrets vault is available on Solo and Agency plans. Attempting to include a secret item on a Free plan returns plan_required.
Why secrets are different
Regular items (text, file, color, URL) store their submitted values in plaintext in the database. That is appropriate for non-sensitive content.
Secret items work differently:
- The client fills in a masked input field on the portal
- Before the value leaves the client's browser, it is encrypted using a libsodium sealed box with BriefGate's public key
- The ciphertext is stored in the database — the plaintext never touches BriefGate's servers in unencrypted form
- The private key exists only in the server environment (never in the database)
- Even a complete database dump cannot reveal secret values
The private key is a 32-byte libsodium keypair secret. On self-hosted deployments, you generate your own keypair and control both sides.
Declaring a secret item
Include it in items[] when calling define_intake:
{
"key": "wp_admin",
"type": "secret",
"label": "WordPress admin credentials",
"help": "Your username and password. Encrypted end-to-end, revealed only once to your developer."
}On the portal, the client sees:
- A masked input (characters hidden as they type)
- A lock icon
- The note: "This will be encrypted and shown to your developer only once."
There is no way to recover the value through the portal after submission.
One-time reveal flow
Step 1. Call get_intake_results (MCP or GET /v1/intakes/:id/results).
On the first call, secret items include the decrypted plaintext:
{
"wp_admin": {
"value": "admin:MyPassword123",
"one_time": true,
"first_reveal": true,
"expires_at": "2026-08-15T10:00:00Z"
}
}Step 2. Store the value in your own secrets manager. This is your only chance.
On all subsequent calls to the same endpoint, value is omitted:
{
"wp_admin": {
"value": null,
"one_time": true,
"first_reveal": false,
"expires_at": "2026-08-15T10:00:00Z"
}
}If the secret expires (30 days after submission) before you collect it:
Call request_revision(intake_id, "wp_admin", "Credentials expired before we could retrieve them. Please resubmit.") to ask the client to enter them again.
The API key used for retrieval must have the secrets:read or admin scope.
Audit trail
Every reveal is logged with:
- Actor (which API key made the call)
- IP address of the caller
- Timestamp
intake_idanditem_key
View the audit log:
GET /v1/audit?action=secret.revealedFilter by intake:
GET /v1/audit?action=secret.revealed&intake_id=int_01J3K...This log is append-only and cannot be deleted.
Auto-expiry
Secrets expire 30 days after the client submits the item. This is the default. On self-hosted deployments, set SECRETS_TTL_DAYS in your environment.
An expired secret has value: null and cannot be retrieved. Use request_revision to ask the client to resubmit.
Best practices for agents
Store immediately. When get_intake_results returns a secret with first_reveal: true, store the value before the call returns. It is never available again through the API.
Store in a secrets manager. After revealing, put the value in your secrets manager (1Password, Vault, AWS Secrets Manager, etc.). Do not write it to a file, log it, or include it in a commit.
Never log the revealed value. Even at debug level. If your logger captures variables, mask secrets before passing them to any logging function.
Rotate after use. Once you have finished using a credential (e.g., after deploying the site), inform the client that they can rotate it. The captured credential was valid at collection time; rotating it limits exposure if the value was ever stored unsafely.
Availability
| Plan | Secrets vault |
|---|---|
| Free | Not available — plan_required error |
| Solo | Available |
| Agency | Available |