---
title: "Secrets in functions"
description: "Declare Rayfin secrets with the CLI, read them as typed ctx.Secrets properties, and supply local values through local.settings.json."
url: https://rayfin.ai/docs/functions/secrets
markdown_url: https://rayfin.ai/docs/functions/secrets.md
section: functions
product: Rayfin
sdk_version: 1.36.2
cli_version: 1.36.2
applies_to: "@microsoft/fabric-user-data-functions >= 1.36"
last_updated: 2026-10-03T17:23:06-07:00
source: functions/secrets.mdx
---

# Secrets in functions

> Declare Rayfin secrets with the CLI, read them as typed ctx.Secrets properties, and supply local values through local.settings.json.

[New in 1.36](/docs/reference/changelog#rayfin-136)

Use function secrets for values that must stay server-side: API keys, connection strings, signing keys, and service tokens. Declare them with `rayfin secret set`, then read them in a function through `ctx.Secrets.<NAME>`.

> [!NOTE]
> Functions are generally available in Rayfin 1.36 and are not available in every Fabric region or tenant.

## Declare a secret before reading it [#declare-a-secret-before-reading-it]

```bash
npx rayfin secret set THIRD_PARTY_API_KEY --describe="API key used by summarizeText"
```

The CLI stores the secret value on the deployed Fabric app and records only metadata in `rayfin/rayfin.yml`:

```yaml title="rayfin/rayfin.yml"
secrets:
  - name: THIRD_PARTY_API_KEY
    description: API key used by summarizeText
```

The value is never written to `rayfin.yml`.

## Read the typed secret [#read-the-typed-secret]

```typescript title="rayfin/functions/src/function_app.ts"
import {
  UserDataFunctions,
  type RayfinContext,
} from '@microsoft/fabric-user-data-functions';

export type AppSchema = Record<string, never>;

const udf = new UserDataFunctions();

udf.func(
  'readApiKeyStatus',
  async (ctx: RayfinContext<AppSchema>): Promise<{ configured: boolean }> => {
    const apiKey = ctx.Secrets.THIRD_PARTY_API_KEY;
    return { configured: apiKey.length > 0 };
  },
  [],
);
```

`ctx.Secrets.THIRD_PARTY_API_KEY` is typed as `string`. Reading a name that is not declared in `rayfin.yml` is a TypeScript error.

## How secret typing works [#how-secret-typing-works]

`rayfin secret set` and `rayfin secret delete` regenerate `rayfin/functions/src/secrets.generated.ts`. Functions builds and typegen also ensure the file exists before compiling.

The generated file augments `RayfinSecretRegistry` from `@microsoft/fabric-user-data-functions`:

```typescript title="rayfin/functions/src/secrets.generated.ts"
declare module '@microsoft/fabric-user-data-functions' {
  interface RayfinSecretRegistry {
    THIRD_PARTY_API_KEY: string;
  }
}

export {};
```

Do not import or edit `secrets.generated.ts`. It only needs to be included by the functions `tsconfig.json`.

## Runtime resolution order [#runtime-resolution-order]

When a function reads `ctx.Secrets.<NAME>`, Rayfin resolves the value in this order:

1. The host-provided secret bag delivered with the invocation.
2. `process.env[NAME]`, used mainly for local development.

If a declared secret has no value in either place, the runtime throws:

```text
No value available for secret '<NAME>'. Ensure it is declared in rayfin.yml and set with 'rayfin secret set'.
```

## Use local secrets while debugging [#use-local-secrets-while-debugging]

When you run `npx rayfin dev` or `npx rayfin dev functions apply`, local functions do not receive the deployed secret bag. Put local-only values under `Values` in `local.settings.json`:

```json title="rayfin/functions/local.settings.json"
{
  "IsEncrypted": false,
  "Values": {
    "AzureWebJobsStorage": "",
    "FUNCTIONS_WORKER_RUNTIME": "node",
    "THIRD_PARTY_API_KEY": "local-development-value"
  }
}
```

`local.settings.json` is git-ignored by the scaffold. The CLI merges its own required values into the file and preserves keys you add.

## Migrate from `ctx.getSecret()` [#migrate-from-ctxgetsecret]

`ctx.getSecret(name)` still works, returns `string | undefined`, and falls back to `process.env`, but it is deprecated in 1.36. [Deprecated in 1.36](/docs/reference/changelog#rayfin-136)

```typescript title="rayfin/functions/src/function_app.ts"
const before = ctx.getSecret('THIRD_PARTY_API_KEY');
const after = ctx.Secrets.THIRD_PARTY_API_KEY;
```

Use `ctx.getSecret()` only for a value you intentionally do not model in `rayfin.yml`, and suppress the deprecation locally at that call site.

```prompt title="Move a function secret to typed ctx.Secrets"
In my Rayfin project, update a function that reads a server-side secret.

Declare the secret with `npx rayfin secret set <NAME> --describe="<what it is used for>"` if it is not already in rayfin/rayfin.yml. Replace string-based `ctx.getSecret('<NAME>')` reads with `ctx.Secrets.<NAME>`. Do not put the secret value in source code, chat, `RAYFIN_PUBLIC_*`, or frontend code. For local debugging, add a local-only value under `Values` in rayfin/functions/local.settings.json. Run a TypeScript build or `npx rayfin dev functions apply` long enough to confirm `secrets.generated.ts` and `types.ts` are valid.
```
