Cosmoner Docs
Guides

Project Secrets

Store and reuse sensitive values like API keys, passwords, and tokens across your project's resources. Secrets are encrypted at rest using envelope encryption.

Overview

Project secrets let you store sensitive configuration values — API keys, database passwords, tokens — in one place and reference them across your project's resources. Each secret is encrypted with its own data encryption key (envelope encryption) and the plaintext value is only shown once at creation time.

For non-sensitive configuration values (URLs, feature flags, settings), use project variables instead — they are stored in plaintext, readable at any time, and don't count against your secrets limit.

Prerequisites

  • A project with an active subscription
  • Owner or admin role on the project

Create a Secret

POST /v1/projects/:projectId/secrets
{
  "name": "DB_PASSWORD",
  "value": "my-super-secret-value",
  "description": "Production database password"
}

Secret names must be uppercase letters, numbers, and underscores, starting with a letter (e.g. DB_PASSWORD, STRIPE_API_KEY).

The response includes the plaintext value once. It cannot be retrieved again after this.

Environments

Secrets can be scoped to a deployment environment: development, staging, or production. Pass an environment field when creating a secret; if you omit it, the secret lands in the default environment, which applies everywhere.

The same name can exist once per environment, so you can keep separate DB_PASSWORD values for staging and production:

{
  "name": "DB_PASSWORD",
  "value": "staging-password",
  "environment": "staging"
}

To list only one environment's secrets:

GET /v1/projects/:projectId/secrets?environment=staging
{
  "success": true,
  "data": {
    "id": "...",
    "name": "DB_PASSWORD",
    "description": "Production database password",
    "version": 1,
    "value": "my-super-secret-value",
    "maskedValue": "my••••ue",
    "createdAt": "2025-01-15T10:30:00.000Z"
  }
}

List Secrets

GET /v1/projects/:projectId/secrets

Returns metadata only — names, descriptions, versions, and timestamps. Plaintext values are never included in list responses.

Update a Secret

PATCH /v1/projects/:projectId/secrets/:secretId
{
  "value": "new-secret-value",
  "description": "Updated description"
}

Updating a secret increments its version number and returns the new plaintext value once.

Delete a Secret

DELETE /v1/projects/:projectId/secrets/:secretId

Permanently removes the secret. Any resources referencing it will lose access.

Usage Limits

Each project gets 5 free secrets. You can check your current usage:

GET /v1/projects/:projectId/secrets/usage
{
  "success": true,
  "data": {
    "used": 3,
    "limit": 5,
    "freeLimit": 5,
    "packSize": 5,
    "paidPacks": 0,
    "packPrice": { "monthly": 200, "currency": "USD" }
  }
}

When you reach the limit, creating a new secret returns a 402 error.

Add More Secrets

Each secrets pack adds 5 more secrets to your limit. In the control panel, click Buy more on the Secrets & Variables page to open the upgrade page, choose how many packs you want, and confirm — the page shows your new limit and the added monthly cost before you commit.

The same purchase is available over the API, where packs defaults to 1:

POST /v1/projects/:projectId/secrets/upgrade
{ "packs": 2 }

Packs are billed as subscription items on your project's Stripe subscription, prorated for the current billing period — the project must already have an active subscription (e.g. from another paid resource) before a pack can be added. If you delete secrets and drop back within the free tier, the pack is automatically removed.

Audit Trail

Every create, update, and delete action is logged. View the audit trail for a secret:

GET /v1/projects/:projectId/secrets/:secretId/audit
{
  "success": true,
  "data": [
    {
      "id": "...",
      "action": "CREATED",
      "actor": { "id": "...", "name": "Jane", "email": "[email protected]" },
      "createdAt": "2025-01-15T10:30:00.000Z"
    }
  ]
}

Using Secrets in Apps

Project secrets can be linked directly to app environment variables. Instead of pasting sensitive values into each app's env var configuration, reference a secret from the vault — the actual value is resolved at deploy time.

In the app settings or creation wizard, click Link secret in the environment variables section. Select one or more secrets from the picker. Each linked secret appears as an env var with the secret's name as the key. The value is never exposed in the UI — it shows "Linked to vault" instead.

When the app deploys or redeploys, linked env vars are automatically resolved to their current decrypted values. If you update a secret in the vault, the new value takes effect on the next redeploy.

Linked env vars include projectSecretId in the API payload:

{
  "envVars": [
    { "key": "DB_PASSWORD", "value": "", "secret": true, "projectSecretId": "clx..." }
  ]
}

Security Model

  • Envelope encryption: Each secret has its own AES-256-GCM data encryption key (DEK), which is itself encrypted by a master key (KEK).
  • Write-only API: Plaintext values are returned only at creation or update, never on read or list.
  • Role-based access: Only project owners and admins can create, update, or delete secrets. Members with read access can view metadata only.
  • Audit logging: All mutations are tracked with the acting user and timestamp.

On this page