# How to Integrate Fastio API in Nuxt.js

Integrating Fastio API with Nuxt.js enables Vue developers to build reliable file management and storage directly into their server-rendered applications. Nuxt multiple provides secure server API routes that hide credentials from the client interface. This guide covers the complete integration process, from managing environment variables to handling multipart file uploads and agentic workflows.


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

## Why Integrate Fastio API with Nuxt 3?

Vue and Nuxt frameworks power millions of applications requiring reliable file storage solutions. According to npm, Vue.js receives over 2.8 million weekly downloads. This massive adoption highlights the need for secure, scalable backends to handle the media and documents generated by these frontend clients. Integrating the Fastio API with Nuxt.js connects a responsive user interface with an intelligent workspace backend.

When you integrate Fastio into a Nuxt multiple application, you gain access to an intelligent workspace rather than just commodity storage. Fastio auto-indexes files upon upload, making them searchable by meaning immediately. This built-in intelligence means your application does not need a separate vector database to understand the content your users upload. Nuxt multiple is particularly well-suited for this architecture because its unified server engine, Nitro, allows you to write server-side API routes in the same repository as your Vue components.

These server-side integrations protect sensitive credentials in Nuxt multiple. By keeping your Fastio API keys on the server, you prevent exposing them to the public internet. The client application only communicates with your internal Nuxt endpoints, which then securely proxy the requests to Fastio. This pattern ensures high security while keeping the developer experience straightforward and unified.

## Setting Up Your Nuxt Environment for Fastio

Before writing any application code, you must configure your project environment to securely communicate with the Fastio API. This preparation involves setting up your local environment variables and configuring the Nuxt framework to recognize them. Proper configuration prevents accidental leaks of your workspace administration keys.

Begin by acquiring your API credentials from your Fastio dashboard. You will need a valid API key with appropriate permissions for your target workspace. Generate a key in Settings > Devices & Agents > API Keys, or create one with `POST /current/user/auth/key/`. Authenticated calls use `Authorization: Bearer {api_key}` against `https://api.fast.io/current/`. Once you have your key, create a file named `.env` in the root directory of your Nuxt project.

Inside this file, define your environment variables. You should store both the API key and the specific workspace identifier you intend to use.

```bash
FASTIO_API_KEY=your_secure_api_key_here
FASTIO_WORKSPACE_ID=your_workspace_id_here
```

Next, map these variables into your application configuration. Open `nuxt.config.ts` and use the `runtimeConfig` object to expose these values to your server routes. Nuxt multiple automatically replaces values in `runtimeConfig` with matching environment variables at runtime, ensuring your production deployments pick up the correct keys without code changes.

```typescript
export default defineNuxtConfig({
  runtimeConfig: {
    fastioApiKey: process.env.FASTIO_API_KEY,
    fastioWorkspaceId: process.env.FASTIO_WORKSPACE_ID,
    public: {
      // Expose safe variables to the client if necessary
    }
  }
})
```

By keeping the Fastio configuration out of the `public` object, you guarantee that the browser never receives your API key. This foundational step is non-negotiable for production applications handling user data and agent workspaces.

## How to Create a Server API Route for File Uploads

The most secure way to handle file uploads in a Nuxt application is to pipe them through a server API route. This approach hides your Fastio credentials and allows you to validate or sanitize files before they reach your workspace. Creating a dedicated endpoint in Nuxt multiple requires just a few steps.

Follow these steps to build a secure file upload handler:

1.

**Create the API file**: In your Nuxt project, navigate to the `server/api` directory and create a new file named `upload.post.ts`. The `.post` suffix restricts this endpoint to accept only HTTP POST requests.
2.

**Initialize the event handler**: Use the `defineEventHandler` function provided by Nitro. This function gives you access to the incoming request event.
3.

**Parse multipart data**: Call the `readMultipartFormData` utility to extract the uploaded file from the request body. This method handles the complex parsing of form boundaries automatically.
4. **Construct the Fastio request**: Prepare a new `FormData` object with `name`, `size`, `chunk` (the file bytes), `action=create`, `instance_id` (the workspace ID), and `folder_id` (use `root` for the workspace root).
5.

**Transmit the payload**: Use the global `$fetch` utility to POST the form to `https://api.fast.io/current/upload/`. Include your API key in the `Authorization: Bearer` header.
6.

**Return the response**: A successful small upload returns HTTP 201 with `result`, `id`, and `new_file_id`. Send `new_file_id` back to your Vue client.

Here is the complete implementation for your server route:

```typescript
export default defineEventHandler(async (event) => {
  const config = useRuntimeConfig()
  
  // Parse the incoming file from the Nuxt client
  const formData = await readMultipartFormData(event)
  if (!formData || formData.length === 0) {
    throw createError({ statusCode: 400, statusMessage: 'No file uploaded' })
  }
  
  const fileToUpload = formData[0]
  
  const fileName = fileToUpload.filename || 'upload.bin'
  const fileSize = fileToUpload.data.length

// Prepare the payload for Fastio
  const fastioForm = new FormData()
  fastioForm.append('name', fileName)
  fastioForm.append('size', String(fileSize))
  fastioForm.append('chunk', new Blob([fileToUpload.data], { type: fileToUpload.type }), fileName)
  fastioForm.append('action', 'create')
  fastioForm.append('instance_id', config.fastioWorkspaceId)
  fastioForm.append('folder_id', 'root')
  
  try {
    // Send the file to the Fastio API
    const response = await $fetch('https://api.fast.io/current/upload/', {
      method: 'POST',
      headers: {
        'Authorization': `Bearer ${config.fastioApiKey}`
      },
      body: fastioForm
    })
    
    return { success: true, data: response }
  } catch (error) {
    throw createError({ statusCode: 500, statusMessage: 'Fastio upload failed' })
  }
})
```

This server route acts as a secure intermediary. It offloads the complexity of direct API authentication from your frontend while providing a clean, predictable endpoint for your Vue components to consume.

## Implementing the Vue Client Upload Component

With your secure server route in place, you can build the user interface to accept files. The Vue client component will capture the user's file selection and post it to your internal Nuxt endpoint.

In your Vue template, you need a standard file input element and a button to trigger the submission. Using the Vue Composition API makes managing the upload state straightforward. You can track whether a file is currently uploading and display appropriate feedback to the user.

```vue
<template>
  <div class="upload-container">
    <h2>Upload to Workspace</h2>
    <input type="file" @change="handleFileSelect" accept="image/png, image/jpeg, application/pdf" />
    <button @click="submitFile" :disabled="!selectedFile || isUploading">
      {{ isUploading ? 'Uploading...' : 'Upload File' }}
    </button>
    <p v-if="uploadResult" class="success-message">File uploaded successfully!</p>
    <p v-if="errorMessage" class="error-message">{{ errorMessage }}</p>
  </div>
</template>

<script setup>
import { ref } from 'vue'

const selectedFile = ref(null)
const isUploading = ref(false)
const uploadResult = ref(null)
const errorMessage = ref('')

const handleFileSelect = (event) => {
  const files = event.target.files
  if (files && files.length > 0) {
    selectedFile.value = files[0]
  }
}

const submitFile = async () => {
  if (!selectedFile.value) return
  
  isUploading.value = true
  errorMessage.value = ''
  uploadResult.value = null
  
  const formData = new FormData()
  formData.append('document', selectedFile.value)
  
  try {
    const { data, error } = await useFetch('/api/upload', {
      method: 'POST',
      body: formData
    })
    
    if (error.value) {
      throw new Error(error.value.message || 'Upload failed')
    }
    
    uploadResult.value = data.value
    selectedFile.value = null
  } catch (err) {
    errorMessage.value = err.message
  } finally {
    isUploading.value = false
  }
}
</script>
```

This component uses the built-in `useFetch` composable from Nuxt multiple. When the user selects a file, the component wraps it in a standard `FormData` object and posts it to the `/api/upload` route you created earlier. The user experiences a responsive interface while the server handles the secure transit to the Fastio workspace.

## Retrieving and Listing Workspace Files

Uploading is only half of the integration process. Most applications also need to display the files stored within a workspace. Fetching the directory contents follows the same architectural pattern: a secure server route combined with a reactive client component.

First, create a new server route to handle the listing request. Create a file named `list.get.ts` in your `server/api` directory. This endpoint calls `GET /current/workspace/{workspace_id}/storage/{parent_id}/list/` and returns the folder listing. Use `root` as `parent_id` for the workspace root. The response includes `pagination.has_more`, `pagination.next_cursor`, and `pagination.page_size`. Rely on `has_more` and `next_cursor` when you need the next page.

```typescript
export default defineEventHandler(async (event) => {
  const config = useRuntimeConfig()
  const parentId = 'root'
  
  try {
    const response = await $fetch(`https://api.fast.io/current/workspace/${config.fastioWorkspaceId}/storage/${parentId}/list/?sort_by=name&sort_dir=asc&page_size=100`, {
      method: 'GET',
      headers: {
        'Authorization': `Bearer ${config.fastioApiKey}`
      }
    })
    
    return response
  } catch (error) {
    throw createError({ statusCode: 500, statusMessage: 'Failed to retrieve workspace files' })
  }
})
```

Once the server route is active, your Vue page can fetch this data during the rendering process. Nuxt multiple excels at server-side rendering, allowing you to fetch the folder listing before sending the HTML to the browser. Use the `useAsyncData` composable to load the workspace contents cleanly.

```vue
<script setup>
const { data, pending, error } = await useAsyncData('workspace-files', () => $fetch('/api/list'))
</script>

<template>
  <div class="file-browser">
    <h2>Workspace Files</h2>
    <div v-if="pending">Loading files...</div>
    <div v-else-if="error">Could not load files.</div>
    <p v-else-if="data?.pagination">
      Loaded a page of {{ data.pagination.page_size }} items.
    </p>
  </div>
</template>
```

This pattern keeps credentials on the server. The browser receives rendered HTML once the listing is ready, which improves performance on slower connections.

## Integrating Agentic Features via MCP

Fastio is designed as an intelligent workspace where both humans and AI agents collaborate. When integrating with Nuxt, you can take advantage of these capabilities to build advanced, automated applications. Connect agents at `https://mcp.fast.io/mcp` (or `https://mcp.fast.io/mcp/key` with a Bearer header). Legacy SSE is `https://mcp.fast.io/sse`. Named mode exposes a consolidated MCP toolset, including `upload`, `storage`, `find`, `ai`, and `event`. Code mode for headless agents exposes tools including `auth`, `upload`, `search`, `execute`, `room`, and `how-to`.

For example, your Nuxt backend can start Ripley on a file right after upload. Fastio auto-indexes documents, so your application does not need a separate embedding pipeline or vector database. Ask Ripley through the MCP `ai` tool (`ask`), or start a chat with `POST /current/workspace/{workspace_id}/ai/agent/` and send a message with `POST /current/workspace/{workspace_id}/ai/agent/{chat_id}/message/`.

A typical MCP tools/call looks like this:

```json
{"jsonrpc":"2.0","id":1,"method":"tools/call",
 "params":{"name":"upload","arguments":{"action":"web-import","url":"https://example.com/report.pdf",
 "profile_type":"workspace","profile_id":"1234567890123456789"}}}
```

Connecting agents to the remote MCP server URL gives your environment natural language file management without installing local packages.

Your backend systems can direct agents to read, summarize, or modify files within the shared workspace using standard MCP tool calls. You can also use ownership transfer features. An agent might generate a detailed report, save it to a Fastio workspace, and then transfer ownership of that workspace directly to a human user account. The human user then interacts with those files through the UI of your Nuxt application, creating a smoother collaboration loop.

## Handling Advanced Workflows with Activity Polling

Keep your Nuxt app in sync with workspace activity by reading the audit log and long-polling for new events. Your server route can wait for the next change, then refresh a listing or start Ripley on the files that just arrived.

Create a server API route that calls the activity poll endpoint. Pass `wait=95` and the last activity timestamp so Nitro holds the request until Fastio has something new.

```typescript
export default defineEventHandler(async (event) => {
  const config = useRuntimeConfig()
  const query = getQuery(event)
  const entityId = query.entityId
  const lastactivity = query.lastactivity || '0'

try {
    const response = await $fetch(
      `https://api.fast.io/current/activity/poll/${entityId}?wait=95&lastactivity=${lastactivity}`,
      {
        method: 'GET',
        headers: {
          'Authorization': `Bearer ${config.fastioApiKey}`
        }
      }
    )

return response
  } catch (error) {
    throw createError({ statusCode: 500, statusMessage: 'Failed to poll workspace activity' })
  }
})
```

You can also read recent activity with `GET https://api.fast.io/current/events/search/`. When a new file appears, start Ripley with `POST /current/workspace/{workspace_id}/ai/agent/` and send a follow-up with `POST /current/workspace/{workspace_id}/ai/agent/{chat_id}/message/`. Your Nuxt app stays current with the same workspace humans and agents already use.

## Best Practices for Nuxt and API Security

When building integrations that handle files and external APIs, security must remain the top priority. Nuxt provides excellent tools for securing your application, but you must implement them correctly to protect your users and your Fastio workspace.

First, always implement rate limiting on your server API routes. Your Nuxt endpoints that proxy uploads to Fastio are publicly accessible by default. Without rate limiting, malicious users could repeatedly upload large files, consuming your server bandwidth and potentially exhausting your workspace storage limits. You can implement rate limiting using Nitro plugins or specialized middleware that tracks incoming requests by IP address.

Second, validate all file types and sizes on the server before forwarding the request to Fastio. Client-side validation in your Vue components improves the user experience by failing quickly, but it is easily bypassed. Your Nuxt server route must strictly enforce file extensions and maximum payload sizes. Rejecting invalid files early saves processing time and prevents unsupported media from cluttering the shared workspace.

Finally, consider implementing proper authentication for your Nuxt routes. If your application has user accounts, ensure that your upload and list endpoints verify the user's session before communicating with Fastio. This ensures only authorized users can modify workspace contents.

## Frequently asked questions

### How do I upload files to Fastio using Nuxt 3?

You should upload files by creating a secure server API route in your Nuxt multiple project. Your Vue client component captures the file and sends it to this internal endpoint. The server route then uses your stored API keys to forward the file to the Fastio workspace, ensuring your credentials remain hidden from the browser.

### Can I use Fastio API in Vue.js directly?

Yes, you can use the Fastio API directly in a client-side Vue.js application, but it is generally discouraged for security reasons. Exposing your API key in the client browser allows anyone to access your workspace. Using a meta-framework like Nuxt provides a server layer to protect your credentials securely.

### Do I need a vector database to search my Fastio files?

Fastio includes built-in Intelligence Mode that automatically indexes files upon upload. You do not need to connect or maintain a separate vector database. Your Nuxt application can query the workspace using natural language immediately after a file finishes uploading.

### How do I prevent unauthorized file uploads in Nuxt?

You must validate file types and sizes within your server API route before sending the data to Fastio. Combine this server-side validation with session checks to ensure only authenticated users can access the upload endpoint. Client-side validation alone is insufficient for security.

## 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.
