Skip to main content

POST /v1/env/list

List all variables in a stage. Returns metadata only — no plaintext values are included in this response.

Request

curl -X POST https://api.barekey.dev/v1/env/list \
  -H "Authorization: Bearer bk_at_..." \
  -H "Content-Type: application/json" \
  -d '{
    "orgSlug": "acme-42",
    "projectSlug": "backend-api-1234",
    "stageSlug": "production"
  }'
Request body fields:
FieldTypeRequiredDescription
orgSlugstringYesOrg slug
projectSlugstringYesProject slug
stageSlugstringYesStage name

Response

{
  "variables": [
    {
      "name": "DATABASE_URL",
      "kind": "secret",
      "declaredType": "string",
      "createdAtMs": 1700000000000,
      "updatedAtMs": 1700050000000
    },
    {
      "name": "CHECKOUT_FLOW",
      "kind": "ab_roll",
      "declaredType": "string",
      "chance": 0.2,
      "createdAtMs": 1700000100000,
      "updatedAtMs": 1700000100000
    }
  ],
  "requestId": "req_01hx..."
}
Each variable in variables:
FieldTypeAlways presentDescription
namestringYesVariable name
kind"secret" | "ab_roll"YesVariable kind
declaredTypestringNoDeclared type, if set
chancenumberab_roll onlyProbability of returning value A (0.0–1.0)
createdAtMsnumberYesUnix timestamp in milliseconds
updatedAtMsnumberYesUnix timestamp in milliseconds
Variables are returned sorted alphabetically by name.

Error codes

CodeHTTPWhen
UNAUTHORIZED401Invalid or expired token
INVALID_JSON400Request body is not valid JSON
INVALID_REQUEST400Missing required field
INVALID_ORG_SCOPE403Token org doesn’t match orgSlug

POST /v1/env/write

Create, update, or delete variables in a single request. All operations in a write request are applied atomically.

Write modes

The mode field controls how existing variables are handled:
ModeBehavior
"upsert"Create new variables and update existing ones. Existing variables not mentioned in entries are unchanged.
"create_only"Only create new variables. Returns INVALID_REQUEST if any entry refers to a variable that already exists.

Request

curl -X POST https://api.barekey.dev/v1/env/write \
  -H "Authorization: Bearer bk_at_..." \
  -H "Content-Type: application/json" \
  -d '{
    "orgSlug": "acme-42",
    "projectSlug": "backend-api-1234",
    "stageSlug": "production",
    "mode": "upsert",
    "entries": [
      {
        "name": "DATABASE_URL",
        "kind": "secret",
        "value": "postgres://rds.example.com:5432/myapp",
        "declaredType": "string"
      },
      {
        "name": "CHECKOUT_FLOW",
        "kind": "ab_roll",
        "valueA": "original",
        "valueB": "redesigned",
        "chance": 0.2,
        "declaredType": "string"
      }
    ],
    "deletes": ["OLD_API_KEY"]
  }'
Request body fields:
FieldTypeRequiredDescription
orgSlugstringYesOrg slug
projectSlugstringYesProject slug
stageSlugstringYesStage name
mode"upsert" | "create_only"YesHow to handle existing variables
entriesarrayNoVariables to create or update
deletesstring[]NoNames of variables to delete
Each entry for a secret variable:
FieldTypeRequiredDescription
namestringYesVariable name
kind"secret"YesMust be "secret"
valuestringYesPlaintext value
declaredTypestringNoOne of "string", "boolean", "int64", "float", "date", "json"
Each entry for an ab_roll variable:
FieldTypeRequiredDescription
namestringYesVariable name
kind"ab_roll"YesMust be "ab_roll"
valueAstringYesPlaintext value A
valueBstringYesPlaintext value B
chancenumberYesProbability of returning A (0.0–1.0)
declaredTypestringNoDeclared type for both values

Response

{
  "created": ["CHECKOUT_FLOW"],
  "updated": ["DATABASE_URL"],
  "deleted": ["OLD_API_KEY"],
  "requestId": "req_01hx..."
}
Response fields:
FieldTypeDescription
createdstring[]Names of variables that were created
updatedstring[]Names of variables that were updated
deletedstring[]Names of variables that were deleted
requestIdstringRequest trace ID

How writes work

Values are encrypted server-side before being committed to the database. The write goes through a two-phase process:
  1. Prepare — all values are encrypted with the project DEK; storage delta is computed
  2. Reserve — storage usage is reserved in the billing system
  3. Commit — encrypted payloads are written to the database
  4. Settle — storage usage is finalized (or rolled back on failure)
This means a write request that fails validation (e.g. create_only with an existing name) will not encrypt any values or reserve any billing units.

Error codes

CodeHTTPWhen
UNAUTHORIZED401Invalid or expired token
INVALID_JSON400Request body is not valid JSON
INVALID_REQUEST400Missing required field, invalid type value, or create_only conflict
INVALID_ORG_SCOPE403Token org doesn’t match orgSlug
USAGE_LIMIT_EXCEEDED402Storage limit reached on the free plan
BILLING_UNAVAILABLE503Billing system temporarily unavailable