Agent List and Fetch
These routes require the current run-bound agent JWT. They are not available to long-lived agent keys, low-trust review agents, task-bridge keys, or skill-test tokens. List the secrets accessible to the current run without materializing values:delivery is env, api, or both. secretRef is a stable opaque handle,
not secret material or a capability; every consuming route re-authorizes it.
The list never returns values, the internal secretId field, binding IDs, or
config paths. An env.* binding implies read access through this API; an
access.* binding grants API access without environment injection.
Fetch a value only when it is needed. The request has no body and the response
uses Cache-Control: no-store:
secret_access_events and
activity_log; agents must not log or paste fetched values into issues,
comments, or documents.
Agent Secret Proposals
These routes use the same current run-bound agent JWT as the list and fetch routes:kind to binding and identify the source by the
agent’s own existing env.* or access.* config path:
sourceConfigPath must resolve from the proposing agent’s own binding. An
unknown path or another agent’s path returns 404. A binding request must
provide exactly one of sourceConfigPath, secretId, or secretProposalId.
Omit targetAgentId to target the proposing agent; under the default policy a
manager may instead target one of its reports. configPath accepts
env.<KEY> for environment injection or access.<ALIAS> for API-only access.
For a run with a checked-out origin issue, a successful proposal automatically
creates a human-only Confirm secret binding card in that issue. API clients
must not create a second interaction. The card contains only non-secret
metadata: the source label, target agent, new config path, justification, and
expiry.
Selecting Create binding accepts the card and then triggers a separate,
freshly authorized binding write. Card acceptance is not execution. Read
result.secretProposal.status for the actual outcome:
executedmeans the binding write completed.failedmeans the card was accepted but execution failed. The card renders FAILED, exposes a non-secreterrorCode, and Paperclip posts a Secret binding execution failed comment withBinding created: no.rejected,withdrawn, orexpiredmeans no binding was created.
secretProposal.configPath, decision, executionStatus, and instructions.
After any secret card, call GET /api/agents/me/secrets again and confirm the
expected secret metadata and delivery before using the new binding. Acceptance
is not execution; a failed wake or missing metadata means the alias must be
treated as unavailable until a fresh proposal executes successfully.
List Secrets
Create Secret
Provider Health
aws_secrets_manager, an unready health response names the missing
non-secret provider environment variables, the AWS SDK default credential source
expected by the server runtime, and the custody rule that AWS bootstrap
credentials must not be stored in Paperclip company_secrets.
The equivalent CLI check is:
Provider Vaults
Provider vaults are named, company-scoped configurations that route secret material to one of the supported provider backends. See the secrets deploy guide for the operator model and custody rules. All routes below require board auth and company access. Mutating routes emitsecret_provider_config.* activity-log entries. No route in this surface
returns provider credential values; submitting credential-shaped fields in
config is rejected at validation time.
List Vaults
config,
latest health snapshot (healthStatus, healthCheckedAt, healthMessage,
healthDetails), disabledAt, and audit columns.
Create Vault
config shapes:
local_encrypted: optionalbackupReminderAcknowledged: boolean.aws_secrets_manager: requiredregion; optionalnamespace,secretNamePrefix,kmsKeyId,ownerTag,environmentTag.gcp_secret_manager(coming soon): optionalprojectId,location,namespace,secretNamePrefix.vault(coming soon): optional origin-only HTTPSaddress,namespace,mountPath,secretPathPrefix.addressvalues with embedded credentials, paths, query strings, or fragments are rejected.
status defaults to ready for local_encrypted and aws_secrets_manager,
and to coming_soon for gcp_secret_manager and vault. Coming-soon and
disabled vaults cannot be marked isDefault. Setting isDefault: true clears
the previous default for the same provider in the same transaction.
Get Vault
Update Vault
config is replaced wholesale on update — pass the full provider config
payload, not a partial diff. Status transitions for gcp_secret_manager and
vault are constrained to coming_soon and disabled until their runtime
modules ship.
Disable Vault
disabled, isDefault clears, and
disabledAt is stamped. Disabled vaults remain in GET results for audit
purposes but are no longer offered in the secret create/rotate flow.
Set Default
coming_soon or disabled.
Run Health Check
details.guidance may include missing non-secret env names and the
expected AWS SDK credential source; coming-soon vaults always return
status: "coming_soon" with code: "runtime_locked" and never call into
provider modules.
Selecting A Vault When Creating Or Rotating Secrets
POST /api/companies/{companyId}/secrets and
POST /api/secrets/{secretId}/rotate both accept an optional
providerConfigId field that pins the secret to a specific vault. When
omitted (or null), the operation runs through the deployment-level provider
configuration — the same path existing installs already use. The board UI
preselects the company’s default vault for the chosen provider before
submitting, so callers should usually send an explicit providerConfigId.
Coming-soon and disabled vaults are rejected with a 422; a vault that does not
match the secret’s provider is rejected the same way.
Response Redaction Rules
Every route in this surface enforces the same redaction contract:- Secret values are never returned. The board UI never has a “reveal value” affordance; resolution happens server-side at runtime under a binding.
- Provider credential values are never accepted, stored, returned, logged, or echoed in error messages. Submitting credential-shaped fields fails validation with a non-leaking error.
- Activity log entries record vault id, provider, displayName, status, and
isDefault transitions — never
configpayloads or health detail bodies.
Remote Import From AWS Secrets Manager
Remote import links existing AWS Secrets Manager entries into Paperclip asexternal_reference secrets. Import stores provider reference metadata only; it
does not copy the remote secret plaintext into Paperclip.
The routes are board-only and company-scoped. providerConfigId must point to
a same-company AWS provider vault with status ready or warning. Disabled,
coming-soon, non-AWS, and cross-company vaults are rejected. Imported secrets
resolve later through the selected vault, so runtime reads still need
secretsmanager:GetSecretValue and any required KMS decrypt permission on the
selected external secret.
Preview Remote Import Candidates
query is optional and is passed to AWS Secrets Manager inventory filtering.
Treat it as non-secret metadata because AWS may record list request parameters
in CloudTrail. nextToken is an opaque AWS cursor; callers must pass it back
unchanged and must not synthesize offsets. pageSize is optional, defaults to
50 in the UI, and is capped at 100.
Preview uses AWS ListSecrets only. It must not call GetSecretValue or
BatchGetSecretValue, must not request SecretString, and must not require KMS
decrypt. The response contains sanitized metadata for display and conflict
decisions:
ready: the row can be selected for import.duplicate: a Paperclip secret already links the same canonical provider reference for the same provider vault.conflict: the row has a name/key collision or provider guardrail failure.
exact_reference, name, key, and
provider_guardrail. AWS refs under Paperclip’s own managed namespace are
blocked as external references; use the Paperclip-managed secret flow for those
resources instead.
Import Selected Remote References
secrets array accepts 1-100 rows. Each row may override the suggested
Paperclip name, key, optional Paperclip description,
providerVersionRef, and sanitized providerMetadata. Blank descriptions are
stored as null; AWS provider descriptions are not copied into Paperclip
descriptions. The backend re-checks duplicate refs and name/key conflicts at
submit time; a stale preview does not bypass those checks.
The import response is row-level:
imported: Paperclip created an activeexternal_referencesecret and one metadata-only version row.skipped: the row had an exact-reference duplicate or name/key conflict.error: the provider rejected the reference or the row failed validation.
Rotate Secret
"version": "latest"
automatically get the new value on next heartbeat. Pin to a specific version
when a bad latest rollout would affect many agents at once.
Using Secrets in Agent Config
Reference secrets in agent adapter config instead of inline values:secretId. The concrete value is resolved for the run’s responsible user:
required defaults to true and allowMissingOverride defaults to false.
Missing required user-secret values must fail closed before adapter dispatch.
Optional missing values omit the environment variable; they must not inject an
empty string or another user’s value. Paperclip records value-free access
events with secretScope, responsibleUserId, credentialOwnerUserId, and
userSecretDefinitionId.