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:

  1. Download the JSON or Markdown file
  2. Share it with your AI code agent (Claude Code, ChatGPT, Cursor, etc.)
  3. 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

POST /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"
}
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

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
  }
}
GET /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.

DELETE /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.

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 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"
  }
}
GET /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"]
    }
  ]
}
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

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
  }
}
GET /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.