> ## Documentation Index
> Fetch the complete documentation index at: https://docs.mixpeek.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Server Functions

> Run server-side JavaScript and TypeScript in your Canvas app — access environment variables, key-value storage, and the Mixpeek API without exposing secrets.

## Overview

Server functions let you run backend logic inside your Canvas app. Write TypeScript or JavaScript handlers that execute server-side with access to environment variables, a built-in KV store, and `fetch` — without managing infrastructure.

***

## How it works

1. Include server function source files in your deploy's `source_files` map
2. Files under `api/` become HTTP endpoints at `/functions/`
3. Canvas transpiles TypeScript → JavaScript via esbuild and executes your handler in a sandboxed async context

| Source file          | Endpoint                          |
| -------------------- | --------------------------------- |
| `api/hello.ts`       | `GET/POST /functions/hello`       |
| `api/search.js`      | `GET/POST /functions/search`      |
| `api/data/export.ts` | `GET/POST /functions/data/export` |

***

## Writing a server function

Export a default function that receives a context object and returns a response:

```typescript theme={null}
// api/hello.ts
export default async function handler(ctx) {
  const name = ctx.req.query.name || 'world'
  return {
    status: 200,
    body: { message: `Hello, ${name}!` },
  }
}
```

### Context object

Your handler receives a `ctx` object with:

| Property          | Type     | Description                                  |
| ----------------- | -------- | -------------------------------------------- |
| `ctx.req.method`  | `string` | HTTP method (GET, POST, etc.)                |
| `ctx.req.path`    | `string` | Request path                                 |
| `ctx.req.query`   | `object` | URL query parameters                         |
| `ctx.req.body`    | `any`    | Parsed JSON body (for POST/PUT)              |
| `ctx.req.headers` | `object` | Request headers (excluding internal headers) |
| `ctx.env`         | `object` | App environment variables                    |
| `ctx.kv`          | `object` | Key-value store (see below)                  |

### Return value

Return an object with:

| Field     | Type     | Default | Description                                  |
| --------- | -------- | ------- | -------------------------------------------- |
| `status`  | `number` | `200`   | HTTP status code                             |
| `body`    | `any`    | —       | Response body (object → JSON, string → text) |
| `headers` | `object` | `{}`    | Custom response headers                      |

***

## Key-value store

Every app has a built-in Redis-backed KV store, accessible in server functions via `ctx.kv`:

```typescript theme={null}
// api/counter.ts
export default async function handler(ctx) {
  const current = await ctx.kv.get('visit_count')
  const count = parseInt(current || '0') + 1
  await ctx.kv.set('visit_count', String(count))

  return {
    body: { visits: count },
  }
}
```

| Method | Signature                                                         | Description                                              |
| ------ | ----------------------------------------------------------------- | -------------------------------------------------------- |
| `get`  | `kv.get(key: string): Promise<string \| null>`                    | Read a value                                             |
| `set`  | `kv.set(key: string, value: string, ttl?: number): Promise<void>` | Write a value (optional TTL in seconds, default 30 days) |
| `del`  | `kv.del(key: string): Promise<void>`                              | Delete a key                                             |
| `keys` | `kv.keys(): Promise<string[]>`                                    | List all keys for this app                               |

***

## Calling the Mixpeek API

Use `fetch` to call the Mixpeek API through the Canvas proxy — credentials are injected automatically:

```typescript theme={null}
// api/search.ts
export default async function handler(ctx) {
  const { query } = ctx.req.body

  const res = await fetch('https://api.mixpeek.com/v1/retrievers/ret_abc123/execute', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'Authorization': `Bearer ${ctx.env.MIXPEEK_API_KEY}`,
      'X-Namespace': ctx.env.MIXPEEK_NAMESPACE_ID,
    },
    body: JSON.stringify({ inputs: { query }, settings: { limit: 10 } }),
  })

  return { body: await res.json() }
}
```

***

## Deploying with source files

Include your server functions in the `source_files` field when deploying:

```bash theme={null}
curl -X POST https://api.mixpeek.com/v1/apps/$APP_ID/deploy \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "source": "cli_upload",
    "bundle_s3_key": "$BUNDLE_KEY",
    "environment": "production",
    "message": "Add search API route",
    "source_files": {
      "api/hello.ts": "export default async function handler(ctx) {\n  return { body: { message: \"Hello!\" } }\n}",
      "api/search.ts": "export default async function handler(ctx) {\n  // search logic here\n}"
    }
  }'
```

***

## Runtime logging

`console.log`, `console.warn`, `console.error`, and `console.info` calls in server functions are captured and sent to the [runtime logs](/canvas/apps/logs) system. View them in Studio or query via API.

```typescript theme={null}
// api/process.ts
export default async function handler(ctx) {
  console.log('Processing request', ctx.req.method, ctx.req.path)

  try {
    const result = await doWork(ctx.req.body)
    console.info('Success:', result.id)
    return { body: result }
  } catch (err) {
    console.error('Failed:', err.message)
    return { status: 500, body: { error: err.message } }
  }
}
```

***

## Limitations

* **Execution timeout:** 30 seconds per request
* **Request body size:** 1 MB max
* **No filesystem access:** Server functions run in a sandboxed context
* **No npm imports:** Only `fetch` and the `ctx` APIs are available in the execution context
* **TypeScript only:** `.ts` and `.js` files are supported (transpiled via esbuild)

***

## Related

* [Deploy from Code](/canvas/apps/deploy)
* [Runtime Logs](/canvas/apps/logs)
* [Environment Variables](/canvas/apps/environment-variables)
