---
title: "Calling functions from your app"
description: "Invoke Rayfin functions from the frontend with a type-safe FunctionClient — client.functions.<name>.invoke() and error handling."
url: https://rayfin.ai/docs/functions/calling-functions
markdown_url: https://rayfin.ai/docs/functions/calling-functions.md
section: functions
product: Rayfin
sdk_version: 1.34.0
cli_version: 1.33.2
last_updated: 2026-08-23T15:47:11-07:00
source: functions/calling-functions.mdx
---

# Calling functions from your app

> Invoke Rayfin functions from the frontend with a type-safe FunctionClient — client.functions.<name>.invoke() and error handling.

Once a function is registered and its schema is generated (see
[Writing a function](/docs/functions/writing-functions)), calling it from the frontend is a
single typed call through `RayfinClient` — no separate HTTP client or manual request
shaping.

> [!WARNING]
> Functions are experimental and are not available in every Fabric region or tenant. See
> [Functions](/docs/functions) before you depend on them.

## Give `RayfinClient` your functions schema [#give-rayfinclient-your-functions-schema]

Import the generated `AppFunctionsSchema` from your functions project and pass it as
`RayfinClient`'s second type parameter, alongside your data schema:

```typescript title="src/services/rayfinClient.ts"
import { RayfinClient } from '@microsoft/rayfin-client';
import type { AppFunctionsSchema } from '../../rayfin/functions/src/types.js';
import type { AppSchema } from '../../rayfin/data/schema';

const client = new RayfinClient<AppSchema, AppFunctionsSchema>({
  baseUrl: import.meta.env.VITE_RAYFIN_API_URL,
  publishableKey: import.meta.env.VITE_RAYFIN_PUBLISHABLE_KEY,
});
```

`AppFunctionsSchema` is a closed object type — only the function names it lists are accepted
by `client.functions.<name>.invoke(...)`, and each one's parameter and return types are
checked against the schema entry.

## Invoking a function [#invoking-a-function]

```typescript
// A function with input:
const greeting = await client.functions.helloWorld.invoke({
  firstName: 'Ada',
  lastName: 'Lovelace',
});
console.log(greeting); // typed as string

// A void-input function (RayfinContext-only handler):
const entries = await client.functions.getEntries.invoke();
```

`invoke()` resolves with the function's output directly — `Promise<TOutput>`, not a wrapper
envelope. Pass an options object for extra per-call headers:

```typescript
await client.functions.helloWorld.invoke(
  { firstName: 'Ada', lastName: 'Lovelace' },
  { headers: { 'x-request-id': crypto.randomUUID() } }
);
```

## Handling errors [#handling-errors]

`invoke()` throws rather than returning an error value — by the time it resolves, the result
is safe to use without checking for `undefined`:

```typescript
import { FunctionsError } from '@microsoft/rayfin-functions';

try {
  const result = await client.functions.helloWorld.invoke({ firstName, lastName });
} catch (error) {
  if (error instanceof FunctionsError) {
    console.error('Function invocation failed:', error.message, error.code);
  } else {
    // NetworkError (transport-level issues) or SdkError (anything else
    // unexpected) from @microsoft/rayfin-lib.
    console.error('Unexpected error calling function:', error);
  }
}
```

* A non-empty `errors` array or a non-success status in the underlying response surfaces as
  a `FunctionsError`.
* Network failures are wrapped in a `NetworkError`; anything else unexpected is wrapped in a
  base `SdkError`.
* The server-side `invocationId` is logged via `console.debug` alongside the function name,
  so it's available for correlation without being part of the typed return value.

Never call `client.functions.<name>.invoke()` before functions are deployed — see
[Deploying functions](/docs/functions/deploying) to enable `services.functions` and ship
your functions project with `rayfin up`.

```prompt title="Call a Rayfin function from the frontend"
In my Rayfin app, wire up calling a function from the frontend:

- Update the RayfinClient construction in src/services/rayfinClient.ts to pass
  AppFunctionsSchema (imported from rayfin/functions/src/types.js) as the second type
  parameter, alongside my existing data schema.
- Call client.functions.<name>.invoke(...) with the right typed parameters, and handle
  failures by catching FunctionsError from @microsoft/rayfin-functions specifically before
  falling back to a generic error handler.

Show me the updated client setup and the call site.
```
