REST API Reference
Complete HTTP API reference. Integrate from any language, platform, or runtime.
https://api.agentsecretstore.com/v1Machine-readable OpenAPI spec
The full OpenAPI 3.1 schema is served at https://api.agentsecretstore.com/v1/openapi.json. Use it to generate typed clients, import into Postman or Insomnia, or drive contract tests. It always reflects the deployed API.
Authentication
REST endpoints use Bearer tokens in the Authorization header. Agent keys request scoped tokens, scoped tokens access secrets, and Firebase ID tokens access human-authenticated management endpoints.
# Agent key: request short-lived scoped tokens
curl -X POST https://api.agentsecretstore.com/v1/tokens \
-H "Authorization: Bearer $ASS_AGENT_KEY" \
-H "Content-Type: application/json" \
-d '{"scopes": ["secrets:read:production/gemini/*"], "ttl": "1h"}'
# Scoped token: read, write, list, and import secrets
curl -H "Authorization: Bearer $ASS_SCOPED_TOKEN" \
"https://api.agentsecretstore.com/v1/secrets?namespace=production%2Fgemini"
# Firebase ID token: human-authenticated management endpoints
curl -H "Authorization: Bearer $FIREBASE_ID_TOKEN" \
"https://api.agentsecretstore.com/v1/audit?limit=100&page=1"Path encoding
For secret read/write paths, keep / as the namespace separator and URL-encode individual path segments. For nested namespace listing, use the query form: /v1/secrets?namespace=production%2Fgemini.
/agentsCreate an agent
Register a new agent and receive its API key. The plaintext key is returned only once. Requires Firebase user authentication.
# Create an agent (user-authenticated). The plaintext api_key is
# returned ONCE — store it securely; it cannot be retrieved again.
curl -X POST https://api.agentsecretstore.com/v1/agents \
-H "Authorization: Bearer $FIREBASE_ID_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "inference-agent",
"description": "Runs nightly inference jobs",
"allowed_namespaces": ["production/gemini"],
"allowed_scopes": ["secrets:read:production/gemini/*"],
"ip_allowlist": null
}'
# Response 200 OK:
{
"id": "uuid-here",
"tenant_id": "tenant-uuid",
"name": "inference-agent",
"api_key": "ass_live_...",
"api_key_prefix": "ass_live_abcd",
"allowed_namespaces": ["production/gemini"],
"allowed_scopes": ["secrets:read:production/gemini/*"],
"created_at": "2026-06-01T10:30:00Z"
}/agentsList agents
List all agents for the authenticated tenant. API keys are never returned — only their prefix. Requires Firebase user authentication.
curl https://api.agentsecretstore.com/v1/agents \
-H "Authorization: Bearer $FIREBASE_ID_TOKEN"
# Response 200 OK:
{
"items": [
{
"id": "uuid-here",
"tenant_id": "tenant-uuid",
"name": "inference-agent",
"description": "Runs nightly inference jobs",
"api_key_prefix": "ass_live_abcd",
"allowed_namespaces": ["production/gemini"],
"allowed_scopes": ["secrets:read:production/gemini/*"],
"active": true,
"created_at": "2026-06-01T10:30:00Z",
"last_active_at": "2026-06-01T11:00:00Z"
}
],
"total": 1
}/tokensRequest a scoped token
Request a scoped token with specific permissions. May require approval for sensitive/critical access.
curl -X POST https://api.agentsecretstore.com/v1/tokens \
-H "Authorization: Bearer $ASS_AGENT_KEY" \
-H "Content-Type: application/json" \
-d '{
"scopes": ["secrets:read:production/gemini/*"],
"ttl": "1h",
"max_uses": null,
"ip_allowlist": null
}'
# Response 200 OK (auto-approved):
{
"token": "eyJhbGciOi...",
"token_id": "uuid-here",
"expires_at": "2026-06-01T11:30:00Z",
"requires_approval": false,
"approval_id": null
}
# Response 200 OK (approval required):
{
"token": null,
"token_id": null,
"expires_at": null,
"requires_approval": true,
"approval_id": "00000000-0000-4000-8000-000000000123"
}/tokens/:token_id/revokeRevoke a scoped token
Immediately revoke a previously issued scoped token. Returns 204 No Content. Requires Firebase user authentication.
curl -X POST https://api.agentsecretstore.com/v1/tokens/{token_id}/revoke \
-H "Authorization: Bearer $FIREBASE_ID_TOKEN"
# Response 204 No Content (token revoked).
# 404 NOT_FOUND if the token does not exist for this tenant.
# 409 ALREADY_REVOKED if the token was already revoked./secrets/:secret_pathStore a secret
Create or update a secret. Requires a scoped token with write permission, or a Firebase user token.
curl -X PUT https://api.agentsecretstore.com/v1/secrets/production/gemini/GEMINI_API_KEY \
-H "Authorization: Bearer $ASS_SCOPED_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"value": "gemini-api-key-example",
"secret_type": "api_key",
"access_tier": "sensitive",
"metadata": {"team": "ml", "env": "prod"}
}'
# Response 200 OK:
{
"id": "uuid-here",
"namespace": "production/gemini",
"key": "GEMINI_API_KEY",
"version": 1,
"secret_type": "api_key",
"access_tier": "sensitive",
"metadata": {"team": "ml", "env": "prod"},
"created_at": "2026-06-01T10:30:00Z",
"updated_at": "2026-06-01T10:30:00Z"
}/secrets/:secret_pathGet a secret
Retrieve a secret value. Requires a scoped token with read permission.
curl https://api.agentsecretstore.com/v1/secrets/production/gemini/GEMINI_API_KEY \
-H "Authorization: Bearer $ASS_SCOPED_TOKEN"
# Response 200 OK:
{
"value": "gemini-api-key-example",
"secret_type": "api_key",
"access_tier": "sensitive",
"metadata": {"team": "ml", "env": "prod"},
"version": 1
}/secrets?namespace=:namespaceList secrets in namespace
List secret metadata in a namespace. Values are never returned in list responses. Use the query form for nested namespaces.
curl "https://api.agentsecretstore.com/v1/secrets?namespace=production%2Fgemini&page=1&limit=50" \
-H "Authorization: Bearer $ASS_SCOPED_TOKEN"
# Response 200 OK:
{
"namespace": "production/gemini",
"items": [
{
"namespace": "production/gemini",
"key": "GEMINI_API_KEY",
"version": 1,
"secret_type": "api_key",
"access_tier": "sensitive",
"metadata": {"team": "ml", "env": "prod"},
"created_at": "2026-06-01T10:00:00Z",
"updated_at": "2026-06-01T10:00:00Z",
"expired": false
}
],
"total": 1
}/secrets/namespacesList all namespaces
List all distinct namespaces visible to the authenticated user or agent.
curl "https://api.agentsecretstore.com/v1/secrets/namespaces" \
-H "Authorization: Bearer $ASS_SCOPED_TOKEN"
# Response 200 OK:
{
"namespaces": [
"production",
"production/gemini",
"production/stripe",
"staging"
],
"total": 4
}/secrets/importBulk import secrets
Import secrets from .env format. Requires a scoped token with write permission, or a Firebase user token.
curl -X POST https://api.agentsecretstore.com/v1/secrets/import \
-H "Authorization: Bearer $ASS_SCOPED_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"namespace": "production/gemini",
"content": "GEMINI_API_KEY=gemini-api-key-example",
"secret_type": "api_key",
"access_tier": "standard",
"metadata": {"source": ".env"}
}'
# Response 200 OK:
{
"namespace": "production/gemini",
"imported": ["GEMINI_API_KEY"],
"imported_count": 1
}/secrets/:secret_pathDelete a secret
Move a secret and all its versions to trash. Restore it with POST /trash/:secret_path/restore. Requires Firebase user authentication.
# Move to trash (user-authenticated endpoint, not agent)
curl -X DELETE https://api.agentsecretstore.com/v1/secrets/staging/test/KEY \
-H "Authorization: Bearer $FIREBASE_ID_TOKEN"
# Response 200 OK:
{
"status": "deleted"
}/trashList trash
List deleted secrets that can be restored. A key written again after deletion is live, so it is not listed. Owners see everything; an agent token sees only paths its secrets:read scopes cover.
# List deleted secrets that can be restored. Owners see all; an agent token
# sees only paths its secrets:read scopes cover.
curl https://api.agentsecretstore.com/v1/trash \
-H "Authorization: Bearer $ASS_SCOPED_TOKEN"
# Response 200 OK:
{
"items": [
{
"namespace": "staging/test",
"key": "KEY",
"versions": 3,
"latest_version": 3,
"secret_type": "api_key",
"access_tier": "standard",
"deleted_at": "2026-06-01T10:40:00Z"
}
],
"total": 1
}/trash/:secret_path/restoreRestore a deleted secret
Restore every version removed by the last delete. Requires the owner, or an agent token with secrets:write for the path. Agents cannot restore sensitive or critical secrets. Plan secret limits apply.
# Owner (Firebase ID token), or an agent token with secrets:write:staging/test/KEY
curl -X POST https://api.agentsecretstore.com/v1/trash/staging/test/KEY/restore \
-H "Authorization: Bearer $ASS_SCOPED_TOKEN"
# Response 200 OK: same shape as PUT /v1/secrets
# 403 OWNER_REQUIRED if an agent restores a sensitive or critical secret.
# 409 SECRET_EXISTS if a live secret already uses the path./secret-versions/:secret_pathList secret versions
List the versions of a secret, newest first. Values are never returned. Requires a scoped token with secrets:read, or a Firebase user token. This lives outside /secrets because GET /secrets/:secret_path reads any path.
curl https://api.agentsecretstore.com/v1/secret-versions/production/gemini/GEMINI_API_KEY \
-H "Authorization: Bearer $ASS_SCOPED_TOKEN"
# Response 200 OK (newest first, values are never returned):
{
"namespace": "production/gemini",
"key": "GEMINI_API_KEY",
"current_version": 3,
"items": [
{
"version": 3,
"secret_type": "api_key",
"access_tier": "sensitive",
"created_at": "2026-06-01T10:35:00Z",
"created_by": "agent-uuid"
}
]
}/secret-versions/:secret_path/rollbackRoll back a secret
Copy an earlier version forward as a new current version. The secret keeps its current access tier; a rollback never lowers it. Requires a scoped token with secrets:write, or a Firebase user token.
curl -X POST https://api.agentsecretstore.com/v1/secret-versions/production/gemini/GEMINI_API_KEY/rollback \
-H "Authorization: Bearer $ASS_SCOPED_TOKEN" \
-H "Content-Type: application/json" \
-d '{"version": 1}'
# Response 200 OK: same shape as PUT /v1/secrets. Version 1 is copied
# forward as version 4; history is never rewritten.
# 404 if the version does not exist. 409 ALREADY_CURRENT if it is current./secrets/:secret_path/rotateRotate a secret
Create a new version and revoke existing scoped tokens for that secret. Requires Firebase user authentication.
# Rotation (user-authenticated endpoint)
curl -X POST https://api.agentsecretstore.com/v1/secrets/production/gemini/GEMINI_API_KEY/rotate \
-H "Authorization: Bearer $FIREBASE_ID_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"new_value": "gemini-rotated-key-example"
}'
# Response 200 OK:
{
"namespace": "production/gemini",
"key": "GEMINI_API_KEY",
"version": 2,
"rotated_at": "2026-06-01T10:35:00Z"
}/approvals/:idApproval management
Check, approve, or deny a pending approval request.
# Get approval status (agent-authenticated)
curl https://api.agentsecretstore.com/v1/approvals/agent/{approval_id} \
-H "Authorization: Bearer $ASS_AGENT_KEY"
# Get approval (user-authenticated)
curl https://api.agentsecretstore.com/v1/approvals/{approval_id} \
-H "Authorization: Bearer $FIREBASE_ID_TOKEN"
# Approve a request (user-authenticated)
curl -X POST https://api.agentsecretstore.com/v1/approvals/{approval_id}/approve \
-H "Authorization: Bearer $FIREBASE_ID_TOKEN"
# Deny a request (user-authenticated)
curl -X POST https://api.agentsecretstore.com/v1/approvals/{approval_id}/deny \
-H "Authorization: Bearer $FIREBASE_ID_TOKEN" \
-H "Content-Type: application/json" \
-d '{"reason": "Unexpected access pattern"}'/auditAudit log
Paginated audit events. Requires Firebase user authentication.
curl "https://api.agentsecretstore.com/v1/audit?limit=100&page=1" \
-H "Authorization: Bearer $FIREBASE_ID_TOKEN"
# Response 200 OK:
{
"events": [
{
"id": "uuid-here",
"event_type": "secret.read",
"actor_id": "agent-uuid",
"actor_type": "agent",
"resource_type": "secret",
"resource_id": "secret-uuid",
"metadata": {
"namespace": "production/gemini",
"key": "GEMINI_API_KEY",
"version": 1
},
"ip_address": "10.0.1.50",
"user_agent": "agentsecretstore-sdk/1.0.0",
"created_at": "2026-06-01T10:30:00Z"
}
],
"total": 1,
"page": 1,
"limit": 100
}/meCurrent account profile
Return the authenticated tenant profile with live secret and agent counts. Requires Firebase user authentication.
curl https://api.agentsecretstore.com/v1/me \
-H "Authorization: Bearer $FIREBASE_ID_TOKEN"
# Response 200 OK:
{
"id": "tenant-uuid",
"email": "owner@example.com",
"name": "Acme Inc",
"plan": "solo",
"subscription_status": "active",
"secret_count": 12,
"agent_count": 3,
"notification_preferences": {
"approval_requests": true,
"security_alerts": true
},
"created_at": "2026-05-01T09:00:00Z"
}/meDelete the account
Schedule account deletion on every plan. It needs a sign-in from the last 5 minutes. Nothing is deleted yet: all agents, API keys, OAuth tokens and scoped tokens stop working at once (403 ACCOUNT_PENDING_DELETION), the owner gets an email with a restore link, and a paid subscription is set not to renew. After 30 days a daily job deletes all secrets, agents, tokens and audit history and schedules destruction of the vault KMS key. Wallet signing keys are disabled, not destroyed. One PII-free tenant.purged audit record is kept. POST /me/restore undoes it until purge_at, and GET /me/status includes purge_at. Requires Firebase user authentication.
curl -X DELETE https://api.agentsecretstore.com/v1/me \
-H "Authorization: Bearer $FIREBASE_ID_TOKEN"
# Response 200 OK:
{
"status": "pending_deletion",
"purge_at": "2026-07-01T10:30:00Z"
}
# 401 REAUTH_REQUIRED if the sign-in is older than 5 minutes. Sign in again
# and retry. The dashboard does this for you.
# Undo before purge_at:
curl -X POST https://api.agentsecretstore.com/v1/me/restore \
-H "Authorization: Bearer $FIREBASE_ID_TOKEN"
# 409 NOT_PENDING_DELETION if there is nothing to restore./billing/checkoutCreate a checkout session
Create a Stripe Checkout session for a plan upgrade. Returns the hosted checkout URL. Requires Firebase user authentication.
curl -X POST https://api.agentsecretstore.com/v1/billing/checkout \
-H "Authorization: Bearer $FIREBASE_ID_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"plan": "solo",
"interval": "monthly"
}'
# plan: "solo" | "team" interval: "monthly" | "annual"
# Response 200 OK:
{
"url": "https://checkout.stripe.com/c/pay/cs_...",
"session_id": "cs_test_..."
}/billing/portalOpen the billing portal
Create a Stripe Customer Portal session for managing the existing subscription. Requires Firebase user authentication.
curl -X POST https://api.agentsecretstore.com/v1/billing/portal \
-H "Authorization: Bearer $FIREBASE_ID_TOKEN"
# Response 200 OK:
{
"url": "https://billing.stripe.com/p/session/..."
}
# 404 STRIPE_CUSTOMER_NOT_FOUND if no Stripe customer exists for the tenant.Error codes
| HTTP Status | Error Code | Meaning |
|---|---|---|
| 200 | OK | Success |
| 400 | INVALID_REQUEST | Malformed request body or invalid parameters |
| 401 | UNAUTHORIZED | Missing or invalid agent key / token |
| 401 | REAUTH_REQUIRED | DELETE /me needs a sign-in from the last 5 minutes |
| 403 | SCOPE_DENIED | Token scope does not cover requested resource |
| 403 | OWNER_REQUIRED | An agent tried to restore a sensitive or critical secret |
| 403 | ACCOUNT_PENDING_DELETION | Account deletion is scheduled; restore it with POST /me/restore |
| 402 | PLAN_LIMIT_REACHED | Plan limit reached; body lists the plans that lift it and their prices |
| 404 | SECRET_NOT_FOUND | Secret does not exist |
| 404 | NOT_FOUND | Resource not found |
| 409 | VERSION_CONFLICT | Concurrent secret update, retry |
| 409 | SECRET_EXISTS | A live secret already uses the path being restored |
| 409 | ALREADY_CURRENT | Rollback target is already the current version |
| 409 | NOT_PENDING_DELETION | No scheduled account deletion to restore |
| 410 | SECRET_EXPIRED | Secret has expired |
| 429 | RATE_LIMITED | Too many requests — check Retry-After header |
| 500 | INTERNAL_ERROR | Server error — retry with exponential backoff |
Error response format
# Error response format:
{
"error": {
"code": "SCOPE_DENIED",
"message": "Token scope does not cover path 'production/stripe/STRIPE_SECRET_KEY'"
}
}Rate limits
Secret reads
300 req/min
Token requests
60 req/min
Secret writes
120 req/min
Per client IP, the same on every plan. A limited request gets HTTP 429; check the Retry-After header. Monthly plan quotas are separate and return HTTP 402.