# How to Integrate Fastio API with SvelteKit Applications

Integrating Fastio API with SvelteKit applications lets developers add secure file storage to their apps. Use SvelteKit's server-side form actions to generate upload sessions and stream chunks directly, avoiding client-side API key exposure. Fastio's REST API at https://api.fast.io/current/ supports chunked uploads with generous file allowances. SvelteKit's optimized SSR handles validation and progress tracking smoothly.

Source: https://fast.io/resources/integrate-fastio-api-sveltekit/
Last reviewed: 2026-02-24

## Why Integrate Fastio API with SvelteKit?

SvelteKit developers often need reliable file storage for user uploads, assets, or AI agent outputs. Fastio provides intelligent workspaces with REST API access, AI indexing, and collaboration features.

Direct integration reduces server load. Instead of proxying large files, generate presigned upload sessions server-side. Clients stream chunks in parallel, and Fastio assembles them.

SvelteKit shines here. Form actions run on the server, parsing FormData securely. Endpoints (+server.ts) list files or poll status. SSR ensures fast initial loads.

Compared to Next.js guides, this is tailored for SvelteKit routing and env handling. See Fastio docs at [https://docs.fast.io/](https://docs.fast.io/) for full API reference.

## Prerequisites and Setup

Sign up for Fastio's 14-day Business Trial at [fast.io/pricing](/pricing/) (card required).

Generate an API key: Settings > API Keys. Store it server-only in `.env`:

```
FASTIO_API_KEY=sk_...
```

Create a SvelteKit app:

```
npm create svelte@latest my-fastio-app
cd my-fastio-app
npm install
npm run dev
```

Import keys with `$env/static/private`:

```ts
import { FASTIO_API_KEY } from '$env/static/private';
```

Test connectivity by listing workspaces in a load function.

## Server-Side Authentication Helper

Create `src/lib/fastio.ts` for API calls. Use Bearer tokens; keys don't expire until revoked.

```ts
import { FASTIO_API_KEY } from '$env/static/private';
import type { RequestInit } from 'undici';

export async function apiFetch(endpoint: string, options: RequestInit = {}) {
  const url = `https://api.fast.io/current/${endpoint}`;
  const headers = new Headers({
    'Authorization': `Bearer ${FASTIO_API_KEY}`,
    'Content-Type': 'application/x-www-form-urlencoded',
    ...options.headers as HeadersInit
  });

const res = await fetch(url, { ...options, headers });
  if (!res.ok) {
    const err = await res.text();
    throw new Error(`Fastio API error: ${res.status} - ${err}`);
  }
  return res.json() as Promise<any>;
}
```

Usage in `src/routes/+page.server.ts`:

```ts
import { apiFetch } from '$lib/fastio';
import type { PageServerLoad } from './$types';

export const load: PageServerLoad = async () => {
  const workspaces = await apiFetch('workspaces/');
  return { workspaces };
};
```

This fetches your workspaces. Handle pagination with `limit` and `offset` params.

## Secure File Uploads with Form Actions

Build upload UI in `src/routes/upload/+page.svelte`:

```svelte
<script lang="ts">
  import { enhance } from '$app/forms';
  let formData = $state({});
</script>

<form method="POST" enctype="multipart/form-data" use:enhance={[{}, (data) => { formData = data; }]}>
  <input name="file" type="file" multiple accept="*/*" />
  <button type="submit">Upload Files</button>
</form>

{#if formData.success}
  <p class="success">Uploaded: {formData.filename} (ID: {formData.fileId})</p>
{/if}
{#if formData.error}
  <p class="error">{formData.error}</p>
{/if}
```

Handle in `+page.server.ts`:

```ts
import { apiFetch } from '$lib/fastio';
import { error, fail } from '@sveltejs/kit';
import type { Actions } from './$types';

const CHUNK_SIZE = 5 * 1024 * 1024; // 5MB chunks

export const actions: Actions = {
  default: async ({ request }) => {
    const data = await request.formData();
    const files = data.getAll('file') as File[];

for (const file of files) {
      if (!file.size) continue;

try {
        // Create upload session in specific workspace
        const session = await apiFetch('upload/', {
          method: 'POST',
          body: new URLSearchParams({
            name: file.name.
            size: file.size.toString(),
            action: 'create',
            instance_id: 'your_workspace_id', // Replace with dynamic ID
            folder_id: 'root'
          })
        });

const uploadId = session.response.id;

// Stream and upload chunks
        const reader = file.stream().getReader();
        let offset = 0;
        while (true) {
          const { done, value } = await reader.read();
          if (done) break;

const chunk = value.slice(0, CHUNK_SIZE);
          await apiFetch(`upload/${uploadId}/chunk/`, {
            method: 'POST',
            body: new FormData().append('chunk', new File([chunk], 'chunk'), `${offset}`)
          });
          offset += chunk.length;
        }

// Complete upload
        await apiFetch(`upload/${uploadId}/complete/`, { method: 'POST' });

// Poll until stored
        let status;
        do {
          status = await apiFetch(`upload/${uploadId}/details/?wait=10`);
          await new Promise(r => setTimeout(r, 500));
        } while (status.response.session.status !== 'stored');

return { success: true, filename: file.name, fileId: status.response.session.new_file_id };
      } catch (e) {
        return fail(500, { error: `Upload failed: ${(e as Error).message}` });
      }
    }
  }
};
```

This processes multiple files, chunks large ones, and polls status. Server-side keeps keys safe.

### Client-Side Progress Tracking

For UX, use XMLHttpRequest or fetch with progress events before form submit. Update a Svelte store:

```ts
// stores.ts
export const uploadProgress = writable(0);
```

Bind in component for real-time bar.

## File Listing and Management Endpoints

Create `src/routes/api/files/[workspaceId]/[folderId]?/+server.ts`:

```ts
import { json } from '@sveltejs/kit';
import { apiFetch } from '$lib/fastio';
import type { RequestHandler } from './$types';

export const GET: RequestHandler = async ({ params, url }) => {
  const { workspaceId, folderId = 'root' } = params;
  const limit = Number(url.searchParams.get('limit') ?? 100);

const files = await apiFetch(`workspace/${workspaceId}/storage/${folderId}/?limit=${limit}`);
  return json(files);
};
```

Client fetch: `/api/files/my-workspace/root`. Supports sorting, cursors for pagination.

For downloads, create a durable File Share: `POST /current/workspace/{workspace_id}/create/fileshare/`.

## Error Handling and Best Practices

Fastio errors return `{"result": false, "error": {...}}`. Check `result === true`.

Common issues:

- 413: File too large. Use chunked uploads for larger files.
- 429: Rate limit. Backoff with `X-Rate-Limit-Available`.
- 401: Invalid key. Rotate via UI.
- Assembly failed: Poll `/upload/{id}/details/?wait=10` longer.

Best practices:

| Practice | Why |
|----------|-----|
| Server-only keys | Prevents client leaks |
| Chunk at 5MB | Balances memory/parallelism |
| Validate MIME/size | Pre-upload checks |
| TypeScript everywhere | `npm i -D @types/*` |
| Env validation | Use `zod` for runtime checks |

Test edge cases: 0-byte files, interruptions (resume chunks via offset).

Deploy to Vercel: Serverless form actions work; ephemeral env ok with secrets.

## Advanced Features: Resumable Uploads and Integration

For resumable, track uploaded chunks via `/upload/{id}/details/`, re-upload missing `order`.

Integrate Svelte stores for multi-file progress:

```ts
// Global progress across uploads
const globalProgress = derived([uploadProgress, totalSize], ([p, t]) => (p / t) * 100);
```

Use Fastio AI: Post-upload, query files with `/ai/chat/` endpoints.

Deployment: Vercel/Netlify adapters handle serverless. Static private env for keys.

## Frequently asked questions

### How do I handle file uploads in SvelteKit?

Use +page.server.ts form actions to parse FormData server-side. Stream files, validate, and process without exposing keys to the client.

### Can I use Fastio API in SvelteKit endpoints?

Yes, create +server.ts routes for GET/POST. Use fetch with private env keys for listing, downloads, or management.

### What's the max file size for Fastio uploads?

Fastio supports chunked uploads for large files via the upload sessions API. See /pricing/ for storage allowances.

### Does Fastio have a SvelteKit SDK?

No official SDK. Use native fetch as shown - lightweight and full control over requests.

### How to resume interrupted uploads?

Poll /upload/{id}/details/ for chunk status. Re-upload missing orders from offset.

### Serverless deployment issues?

Works on Vercel/Netlify. Use private env vars; form actions timeout at 10s - chunk aggressively.

### Integrate with SvelteKit stores?

Yes, writable stores for progress, errors. Update on form events or API polls.

## About Fast.io

Fast.io provides shared workspaces where people and AI agents work on the same files, with built-in semantic search and citation-backed chat over what they hold. Agents reach it through a remote MCP server at https://mcp.fast.io/mcp, a REST API at https://api.fast.io/current/, and a command line client published on npm as @vividengine/fastio-cli.
