AI Agent Integration Guide
Complete guide for AI code agents (Claude Code, ChatGPT, Cursor, etc.) to implement Files Hub file storage in any application.
Download for AI Agents
Download the integration specification files to provide to your AI code agent for automatic implementation.
How to use:
- Download the JSON or Markdown file
- Share it with your AI code agent (Claude Code, ChatGPT, Cursor, etc.)
- Ask the agent to implement Files Hub file storage using the specification
Quick Start
1. Add Environment Variables
Add these to your .env file:
# Required
FILES_HUB_API_KEY=fh_live_your_api_key_here
FILES_HUB_BASE_URL=https://fileshub.zaions.com
# Optional (for mobile apps with restricted API keys)
# FILES_HUB_APP_ID=com.example.myapp
Add to .env.example:
# 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
npm install @files-hub/sdk
# or
yarn add @files-hub/sdk
# or
pnpm add @files-hub/sdk
3. Initialize Client
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
Base URL: https://fileshub.zaions.com/api/v1
Authentication: Include API key in X-API-Key header
/api/v1/objects
Upload a new file
Request Body (multipart/form-data)
| Field | Type | Required | Description |
|---|---|---|---|
file |
file | Yes | The file to upload |
visibility |
string | No | public or private (default: private) |
cURL Example
curl -X POST "https://fileshub.zaions.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)
{
"public_id": "01HXYZ123ABC456DEF789GHI",
"project_id": "01HXYZ000PROJECT123456",
"visibility": "private",
"mime_type": "application/pdf",
"size_bytes": 102400,
"url": "https://fileshub.zaions.com/api/v1/objects/01HXYZ123ABC456DEF789GHI",
"created_at": "2024-01-15T10:30:00.000Z"
}
/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
curl -X GET "https://fileshub.zaions.com/api/v1/objects?page=1&per_page=20" \
-H "X-API-Key: fh_live_your_api_key"
Response (200 OK)
{
"data": [
{
"public_id": "01HXYZ123ABC456DEF789GHI",
"original_filename": "document.pdf",
"mime_type": "application/pdf",
"size_bytes": 102400,
"visibility": "private",
"url": "https://fileshub.zaions.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
}
}
/api/v1/objects/{public_id}
Download a file (public files don't require authentication)
cURL Example
curl -X GET "https://fileshub.zaions.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.
/api/v1/objects/{public_id}
Delete a file from storage
cURL Example
curl -X DELETE "https://fileshub.zaions.com/api/v1/objects/01HXYZ123ABC" \
-H "X-API-Key: fh_live_your_api_key"
Response (200 OK)
{
"message": "Deleted"
}
Email API Reference
Permission Required: API key must have email permission enabled.
/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 display name |
template |
string | Yes* | Template slug (required 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 scheduled sending |
cURL Example (Template)
curl -X POST "https://fileshub.zaions.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 |
|---|---|---|---|
subject |
string | Yes | Email subject line (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)
curl -X POST "https://fileshub.zaions.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)
{
"success": true,
"data": {
"id": "01HXYZ123ABC456DEF789",
"status": "sent",
"scheduled_at": null,
"sent_at": "2024-01-15T10:30:00Z"
}
}
/api/v1/emails/templates
List available email templates
cURL Example
curl -X GET "https://fileshub.zaions.com/api/v1/emails/templates" \
-H "X-API-Key: fh_live_your_api_key"
Response (200 OK)
{
"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"]
}
]
}
/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
curl -X GET "https://fileshub.zaions.com/api/v1/emails?page=1&status=sent" \
-H "X-API-Key: fh_live_your_api_key"
Response (200 OK)
{
"success": true,
"data": [
{
"id": "01HXYZ123ABC",
"to_email": "user@example.com",
"subject": "Welcome!",
"template": "welcome",
"status": "sent",
"scheduled_at": null,
"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
}
}
/api/v1/emails/{public_id}
Get details of a specific email
cURL Example
curl -X GET "https://fileshub.zaions.com/api/v1/emails/01HXYZ123ABC" \
-H "X-API-Key: fh_live_your_api_key"
Response (200 OK)
{
"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"
}
}
SDK Methods
upload()
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()
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()
// Get URL without network request (for public files)
const url = client.getObjectUrl('01HXYZ123ABC');
// Use directly: <img src={url} />
download()
// Download as Blob (for private files or programmatic access)
const blob = await client.download('01HXYZ123ABC');
const objectUrl = URL.createObjectURL(blob);
delete()
await client.delete('01HXYZ123ABC');
Error Handling
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 React Example
// 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 [uploadedUrl, setUploadedUrl] = useState<string | null>(null);
const handleUpload = async (e: React.ChangeEvent<HTMLInputElement>) => {
const file = e.target.files?.[0];
if (!file) return;
setUploading(true);
try {
const result = await client.upload(file, { visibility: 'public' });
setUploadedUrl(result.url);
} catch (error) {
console.error('Upload failed:', error);
} finally {
setUploading(false);
}
};
return (
<div>
<input type="file" onChange={handleUpload} disabled={uploading} />
{uploadedUrl && <p>Uploaded: {uploadedUrl}</p>}
</div>
);
}
TypeScript Types
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;
}
Best Practices
- Never hardcode API keys - Always use environment variables
- Use private visibility for sensitive files that should require authentication
- Implement error handling for all API calls
- Cache the client instance - Don't create new instances per request
- Implement retry logic with exponential backoff for rate limits
- Use getObjectUrl() for public file URLs (no network request needed)
- Use download() for private files or programmatic access
Rate Limits
- Default: 60 requests per minute per API key
- Rate limit headers:
X-RateLimit-Limit,X-RateLimit-Remaining,Retry-After
Need Help?
If you have questions or need assistance, please contact us.