# Files Hub - AI Agent Integration Guide > Complete integration guide for AI code agents (Claude Code, ChatGPT, Cursor, etc.) to implement Files Hub file storage in any application. ## Quick Start ### 1. Add Environment Variables Add these to your `.env` file: ```bash # Required FILES_HUB_API_KEY=fh_live_your_api_key_here FILES_HUB_BASE_URL=https://files-hub.example.com # Optional (for mobile apps with restricted API keys) FILES_HUB_APP_ID=com.example.myapp ``` Add to `.env.example`: ```bash # Files Hub Configuration # Get your API key from the Files Hub admin panel FILES_HUB_API_KEY= FILES_HUB_BASE_URL= # Optional: For mobile apps with restricted API keys # FILES_HUB_APP_ID= ``` ### 2. Install SDK ```bash npm install @files-hub/sdk # or yarn add @files-hub/sdk # or pnpm add @files-hub/sdk ``` ### 3. Initialize Client ```typescript import { FilesHubClient } from '@files-hub/sdk'; const client = new FilesHubClient({ baseUrl: process.env.FILES_HUB_BASE_URL + '/api/v1', apiKey: process.env.FILES_HUB_API_KEY, // For mobile apps: // appId: process.env.FILES_HUB_APP_ID }); ``` --- ## API Reference ### Authentication All API requests require an API key in the `X-API-Key` header: ```bash curl -X GET "https://files-hub.example.com/api/v1/objects" \ -H "X-API-Key: fh_live_your_api_key" ``` ### Endpoints #### Upload File **POST** `/api/v1/objects` Upload a file to storage. **Request (multipart/form-data):** | Field | Type | Required | Description | |-------|------|----------|-------------| | `file` | file | Yes | The file to upload | | `visibility` | string | No | `public` or `private` (default: `private`) | **cURL Example:** ```bash curl -X POST "https://files-hub.example.com/api/v1/objects" \ -H "X-API-Key: fh_live_your_api_key" \ -F "file=@/path/to/document.pdf" \ -F "visibility=private" ``` **Response (201 Created):** ```json { "public_id": "01HXYZ123ABC456DEF789GHI", "project_id": "01HXYZ000PROJECT123456", "visibility": "private", "mime_type": "application/pdf", "size_bytes": 102400, "url": "https://files-hub.example.com/api/v1/objects/01HXYZ123ABC456DEF789GHI", "created_at": "2024-01-15T10:30:00.000Z" } ``` --- #### List Files **GET** `/api/v1/objects` List all files with pagination. **Query Parameters:** | Parameter | Type | Default | Description | |-----------|------|---------|-------------| | `page` | integer | 1 | Page number | | `per_page` | integer | 20 | Items per page (max: 100) | | `visibility` | string | - | Filter: `public` or `private` | **cURL Example:** ```bash curl -X GET "https://files-hub.example.com/api/v1/objects?page=1&per_page=20" \ -H "X-API-Key: fh_live_your_api_key" ``` **Response (200 OK):** ```json { "data": [ { "public_id": "01HXYZ123ABC456DEF789GHI", "original_filename": "document.pdf", "mime_type": "application/pdf", "size_bytes": 102400, "visibility": "private", "url": "https://files-hub.example.com/api/v1/objects/01HXYZ123ABC456DEF789GHI", "created_at": "2024-01-15T10:30:00.000Z" } ], "meta": { "current_page": 1, "per_page": 20, "total": 150, "last_page": 8 } } ``` --- #### Download/Get File **GET** `/api/v1/objects/{public_id}` Download a file. Public files don't require authentication. **Path Parameters:** | Parameter | Type | Description | |-----------|------|-------------| | `public_id` | string | Unique file identifier (ULID) | **cURL Example:** ```bash curl -X GET "https://files-hub.example.com/api/v1/objects/01HXYZ123ABC" \ -H "X-API-Key: fh_live_your_api_key" \ -o downloaded_file.pdf ``` **Response:** Raw file binary with appropriate Content-Type header. --- #### Delete File **DELETE** `/api/v1/objects/{public_id}` Delete a file from storage. **cURL Example:** ```bash curl -X DELETE "https://files-hub.example.com/api/v1/objects/01HXYZ123ABC" \ -H "X-API-Key: fh_live_your_api_key" ``` **Response (200 OK):** ```json { "message": "Deleted" } ``` --- ### Email API Files Hub also provides a powerful email sending API. Send transactional emails using pre-defined templates or custom content. > **Permission Required:** API key must have `email` permission to send emails. #### Send Email **POST** `/api/v1/emails/send` Send an email using a template or raw content. **Request Body (Template-Based):** | Field | Type | Required | Description | |-------|------|----------|-------------| | `to` | string | Yes | Recipient email address | | `to_name` | string | No | Recipient name | | `template` | string | Yes* | Template slug (for template emails) | | `variables` | object | No | Template variables (key-value pairs) | | `cc` | array | No | CC email addresses (max 10) | | `bcc` | array | No | BCC email addresses (max 10) | | `reply_to` | string | No | Reply-to email address | | `attachments` | array | No | StoredObject public_ids (max 5) | | `scheduled_at` | string | No | ISO 8601 datetime for scheduling | **cURL Example (Template):** ```bash curl -X POST "https://files-hub.example.com/api/v1/emails/send" \ -H "X-API-Key: fh_live_your_api_key" \ -H "Content-Type: application/json" \ -d '{ "to": "user@example.com", "to_name": "John Doe", "template": "welcome", "variables": { "name": "John", "company": "Acme Inc" } }' ``` **Request Body (Raw Content):** | Field | Type | Required | Description | |-------|------|----------|-------------| | `to` | string | Yes | Recipient email address | | `subject` | string | Yes | Email subject (max 500 chars) | | `body_html` | string | Yes* | HTML body (required if no body_text) | | `body_text` | string | Yes* | Plain text body (required if no body_html) | **cURL Example (Raw Content):** ```bash curl -X POST "https://files-hub.example.com/api/v1/emails/send" \ -H "X-API-Key: fh_live_your_api_key" \ -H "Content-Type: application/json" \ -d '{ "to": "user@example.com", "subject": "Order Confirmation", "body_html": "

Order Confirmed

Thank you!

", "body_text": "Order Confirmed\n\nThank you!" }' ``` **Response (201 Created):** ```json { "success": true, "data": { "id": "01HXYZ123ABC456DEF789", "status": "sent", "scheduled_at": null, "sent_at": "2024-01-15T10:30:00Z" } } ``` --- #### List Email Templates **GET** `/api/v1/emails/templates` List available email templates. **cURL Example:** ```bash curl -X GET "https://files-hub.example.com/api/v1/emails/templates" \ -H "X-API-Key: fh_live_your_api_key" ``` **Response (200 OK):** ```json { "success": true, "data": [ { "slug": "welcome", "name": "Welcome Email", "description": "Sent to new users", "category": "onboarding", "subject": "Welcome to {{ app_name }}!", "variables": ["name", "company", "login_url"] } ] } ``` --- #### List Email Logs **GET** `/api/v1/emails` List email logs with pagination. **Query Parameters:** | Parameter | Type | Default | Description | |-----------|------|---------|-------------| | `page` | integer | 1 | Page number | | `per_page` | integer | 50 | Items per page (max: 100) | | `status` | string | - | Filter: `pending`, `sent`, `failed`, `scheduled` | **cURL Example:** ```bash curl -X GET "https://files-hub.example.com/api/v1/emails?status=sent" \ -H "X-API-Key: fh_live_your_api_key" ``` **Response (200 OK):** ```json { "success": true, "data": [ { "id": "01HXYZ123ABC", "to_email": "user@example.com", "subject": "Welcome!", "template": "welcome", "status": "sent", "sent_at": "2024-01-15T10:30:00Z", "created_at": "2024-01-15T10:30:00Z" } ], "meta": { "current_page": 1, "last_page": 3, "per_page": 50, "total": 142 } } ``` --- #### Get Email Details **GET** `/api/v1/emails/{public_id}` Get details of a specific email. **cURL Example:** ```bash curl -X GET "https://files-hub.example.com/api/v1/emails/01HXYZ123ABC" \ -H "X-API-Key: fh_live_your_api_key" ``` **Response (200 OK):** ```json { "success": true, "data": { "id": "01HXYZ123ABC", "to_email": "user@example.com", "to_name": "John Doe", "cc_emails": ["manager@example.com"], "bcc_emails": null, "from_email": "noreply@yourapp.com", "from_name": "Your App", "reply_to": "support@yourapp.com", "subject": "Welcome!", "template": "welcome", "status": "sent", "error_message": null, "scheduled_at": null, "sent_at": "2024-01-15T10:30:00Z", "created_at": "2024-01-15T10:30:00Z" } } ``` --- #### Health Check **GET** `/api/health` (no authentication required) ```bash curl -X GET "https://files-hub.example.com/api/health" ``` **Response:** ```json { "status": "ok", "app": "files-hub", "version": "1.0.0", "database": "ok", "timestamp": "2024-01-15T10:30:00.000Z" } ``` --- ## SDK Methods ### upload() ```typescript const result = await client.upload(file, { visibility: 'public' // or 'private' }); console.log(result.url); // URL to access the file console.log(result.public_id); // Unique identifier ``` ### list() ```typescript const { data: files, meta } = await client.list({ page: 1, perPage: 20, visibility: 'public' // optional filter }); console.log(`Page ${meta.current_page} of ${meta.last_page}`); console.log(`Total files: ${meta.total}`); ``` ### getObjectUrl() ```typescript // Get URL without network request (for public files) const url = client.getObjectUrl('01HXYZ123ABC'); // Use directly: ``` ### download() ```typescript // Download as Blob (for private files or programmatic access) const blob = await client.download('01HXYZ123ABC'); const objectUrl = URL.createObjectURL(blob); ``` ### delete() ```typescript await client.delete('01HXYZ123ABC'); ``` ### health() ```typescript const status = await client.health(); if (status.status === 'ok') { console.log('API is healthy'); } ``` --- ## Error Handling ```typescript import { isFilesHubError, FilesHubAuthError, FilesHubNotFoundError, FilesHubRateLimitError } from '@files-hub/sdk'; try { await client.upload(file); } catch (error) { if (error instanceof FilesHubAuthError) { // 401/403 - Authentication failed console.error('Check your API key'); } else if (error instanceof FilesHubNotFoundError) { // 404 - File not found console.error('File does not exist'); } else if (error instanceof FilesHubRateLimitError) { // 429 - Rate limited console.error('Too many requests, try again later'); } else if (isFilesHubError(error)) { // Other API errors console.error('API error:', error.message); } else { throw error; } } ``` --- ## Complete Implementation Examples ### React Example ```typescript // hooks/useFilesHub.ts import { FilesHubClient } from '@files-hub/sdk'; import { useMemo } from 'react'; export function useFilesHub() { const client = useMemo(() => new FilesHubClient({ baseUrl: import.meta.env.VITE_FILES_HUB_BASE_URL + '/api/v1', apiKey: import.meta.env.VITE_FILES_HUB_API_KEY }), []); return client; } // components/FileUploader.tsx import { useFilesHub } from '../hooks/useFilesHub'; import { useState } from 'react'; export function FileUploader() { const client = useFilesHub(); const [uploading, setUploading] = useState(false); const handleUpload = async (e: React.ChangeEvent) => { const file = e.target.files?.[0]; if (!file) return; setUploading(true); try { const result = await client.upload(file, { visibility: 'public' }); console.log('Uploaded:', result.url); } catch (error) { console.error('Upload failed:', error); } finally { setUploading(false); } }; return ( ); } ``` ### Node.js/Express Example ```typescript // services/filesHub.ts import { FilesHubClient } from '@files-hub/sdk'; import fetch from 'node-fetch'; export const filesHubClient = new FilesHubClient({ baseUrl: process.env.FILES_HUB_BASE_URL + '/api/v1', apiKey: process.env.FILES_HUB_API_KEY, customFetch: fetch as any }); // routes/upload.ts import express from 'express'; import multer from 'multer'; import { filesHubClient } from '../services/filesHub'; const upload = multer({ storage: multer.memoryStorage() }); const router = express.Router(); router.post('/upload', upload.single('file'), async (req, res) => { try { if (!req.file) { return res.status(400).json({ error: 'No file provided' }); } const blob = new Blob([req.file.buffer], { type: req.file.mimetype }); const result = await filesHubClient.upload(blob, { visibility: 'private', filename: req.file.originalname }); res.json({ url: result.url, id: result.public_id }); } catch (error) { res.status(500).json({ error: 'Upload failed' }); } }); export default router; ``` ### Next.js API Route Example ```typescript // app/api/upload/route.ts import { FilesHubClient } from '@files-hub/sdk'; import { NextRequest, NextResponse } from 'next/server'; const client = new FilesHubClient({ baseUrl: process.env.FILES_HUB_BASE_URL + '/api/v1', apiKey: process.env.FILES_HUB_API_KEY }); export async function POST(request: NextRequest) { const formData = await request.formData(); const file = formData.get('file') as File; if (!file) { return NextResponse.json({ error: 'No file' }, { status: 400 }); } try { const result = await client.upload(file, { visibility: 'public' }); return NextResponse.json(result); } catch (error) { return NextResponse.json({ error: 'Upload failed' }, { status: 500 }); } } ``` --- ## TypeScript Types ```typescript interface UploadedObject { public_id: string; // ULID identifier project_id: string; // Project ULID visibility: 'public' | 'private'; mime_type: string | null; size_bytes: number; url: string; created_at?: string; // ISO 8601 format } interface ListedObject { public_id: string; original_filename: string; mime_type: string; size_bytes: number; visibility: 'public' | 'private'; url: string; created_at: string; } interface ListObjectsResponse { data: ListedObject[]; meta: PaginationMeta; } interface PaginationMeta { current_page: number; per_page: number; total: number; last_page?: number; } ``` --- ## Rate Limits ### File Storage API - Uploads: 60 requests per minute per API key - Other requests: 120 requests per minute ### Email API - Send emails: 60 requests per minute (configurable per API key) - Daily limit: 450 emails per day per email account (configurable in admin) ### Rate Limit Headers - `X-RateLimit-Limit` - `X-RateLimit-Remaining` - `Retry-After` (when rate limited) --- ## Best Practices 1. **Never hardcode API keys** - Always use environment variables 2. **Use private visibility** for sensitive files 3. **Implement error handling** for all API calls 4. **Cache the client instance** - Don't create new instances per request 5. **Implement retry logic** with exponential backoff for rate limits 6. **Use getObjectUrl()** for public file URLs (no network request) 7. **Use download()** for private files or programmatic access --- ## Support - Documentation: https://files-hub.example.com/ai-integration - API Docs: https://files-hub.example.com/docs - Contact: aoneahsan@gmail.com