Amba

Secrets

Store credentials your functions need — third-party API keys, tokens, signing secrets — encrypted at rest, never readable back in plaintext, scoped to one function or shared across the whole project.

When a function needs a credential — a third-party API key, a webhook signing secret, your own developer token — set it as a secret and read it from env inside the handler. Secrets are encrypted at rest and synced to the runtime within seconds. Plaintext is never returned: once set, you can see a secret's name and sync status, but never its value.

A secret is either function-scoped (bound to one function) or project-wide (shared by every function in the project). Project-wide is the default — omit the function and one value reaches every function, including ones you deploy later. Scope to a single function when only that function should see the value.

The everyday path is the CLI (amba secrets set NAME value) and the amba_secrets_* MCP tools. The REST surface below is what both wrap; routes mount under /v1/admin/projects/:projectId/secrets.

Set a secret

Omit the function for a project-wide secret — every function in the project sees it:

amba secrets set OPENAI_API_KEY sk-…

Add --function to scope it to one function:

amba secrets set STRIPE_API_KEY sk_live_… --function checkout

Or via REST — include function to scope, omit it for project-wide:

# Project-wide
curl -X POST 'https://api.amba.dev/v1/admin/projects/$PROJECT_ID/secrets' \
  -H 'Authorization: Bearer $AMBA_PAT' \
  -H 'Content-Type: application/json' \
  -d '{ "name": "OPENAI_API_KEY", "value": "sk-…" }'
 
# Function-scoped
curl -X POST 'https://api.amba.dev/v1/admin/projects/$PROJECT_ID/secrets' \
  -H 'Authorization: Bearer $AMBA_PAT' \
  -H 'Content-Type: application/json' \
  -d '{ "name": "STRIPE_API_KEY", "value": "sk_live_…", "function": "checkout" }'

For a project-wide secret, function comes back null:

{
  "data": {
    "name": "OPENAI_API_KEY",
    "function": null,
    "version": 1,
    "version_path": "…",
    "sync_status": "pending",
    "created_at": "2026-05-27T10:00:00.000Z"
  }
}

Setting a secret that already exists writes a new version and re-syncs. The function picks up the new value once sync_status flips to synced (typically under 30 seconds).

Set before you deploy

You don't need an existing deployment to set a secret. Set everything your functions will need first, then deploy once — the sync drains as soon as the deployment lands, and amba functions deploy re-syncs at the end of a deploy to pick up anything set in the meantime. This works for both project-wide and function-scoped secrets.

# Set all your secrets up front…
amba secrets set OPENAI_API_KEY sk-…
amba secrets set STRIPE_API_KEY sk_live_… --function checkout
 
# …then deploy. The values are already waiting.
amba functions deploy ./functions/checkout.ts

Rules

  • Secret name must match ^[A-Z][A-Z0-9_]{0,62}$ (uppercase env-var shape).
  • Function name, when given, must match ^[a-z][a-z0-9_-]{0,57}$. Omit it for a project-wide secret. The function does not need to be deployed yet — secrets can be set before deploy.
  • Value cap is 64 KiB.
  • A handful of binding names are platform-managed and rejected with RESERVED_BINDING: AMBA_API_URL, AMBA_AI_GATEWAY_URL, AMBA_PROJECT_ID, AMBA_INTERNAL_TOKEN, EDGE_HEADER_SIGNING_SECRET, STORAGE, EDGE_DB_PROXY.

Read it in a function

The platform injects each secret as an env binding under its name:

export default {
  async fetch(req: Request, env: Env): Promise<Response> {
    const res = await fetch('https://api.stripe.com/v1/charges', {
      headers: { Authorization: `Bearer ${env.STRIPE_API_KEY}` },
      // …
    });
    return new Response(await res.text(), { status: res.status });
  },
};
 
interface Env {
  STRIPE_API_KEY: string; // injected from the secret above
}

See Runtime for the full list of env bindings.

List and inspect

GET /secrets returns every secret on the project — name, function, version, and sync status. Project-wide secrets come back with function set to null. Plaintext is never included (there is no read-back endpoint). Filter to one function with ?function=.

curl 'https://api.amba.dev/v1/admin/projects/$PROJECT_ID/secrets?function=checkout' \
  -H 'Authorization: Bearer $AMBA_PAT'
{
  "data": [
    {
      "function": "checkout",
      "name": "STRIPE_API_KEY",
      "version": 2,
      "sync_status": "synced",
      "attempts": 1,
      "last_error": null,
      "updated_at": "2026-05-27T10:00:30.000Z"
    }
  ]
}

sync_status is one of pending, syncing, sync_failed_retrying, or synced. A non-null last_error plus a sync_failed_retrying status points at a sync that's still being retried.

Delete

Pass --function (CLI) / ?function= (REST) to delete a function-scoped secret; omit it to delete the project-wide secret of that name:

# Function-scoped
amba secrets unset STRIPE_API_KEY --function checkout
 
# Project-wide
amba secrets unset OPENAI_API_KEY
curl -X DELETE 'https://api.amba.dev/v1/admin/projects/$PROJECT_ID/secrets/STRIPE_API_KEY?function=checkout' \
  -H 'Authorization: Bearer $AMBA_PAT'

Delete removes the value from the backing store and the sync record. The runtime binding is reaped on the function's next deploy — redeploy the function after unsetting a secret to fully clear it. Delete is idempotent; removing a secret that's already gone succeeds.

Endpoints

MethodPathDescription
POST/admin/projects/:projectId/secretsSet or rotate a secret. Omit function for project-wide.
GET/admin/projects/:projectId/secretsList secrets (optional ?function=).
DELETE/admin/projects/:projectId/secrets/:name?function=fnDelete a secret. Omit function to delete the project-wide one.

MCP tools

ToolDoes
amba_secrets_setSet or rotate a secret. Omit function for a project-wide secret.
amba_secrets_listList all secrets (names + sync status).
amba_secrets_getLook up one secret's metadata.
amba_secrets_deleteDelete a secret (idempotent). Omit function for the project-wide one.

On this page