Skip to main content
The Files API enables you to upload and manage files that can be attached to tasks. Files can be uploaded from external URLs or directly from your application using signed upload URLs.
To get access to Files APIs, contact [email protected]

Base URL and Authentication

Base URL: https://api.context.ai/api/v1
All API requests require an API key provided via the Authorization header or x-api-key header:
const response = await fetch('https://api.context.ai/api/v1/files', {
  headers: {
    'Authorization': 'Bearer ctx_your_api_key',
    'Content-Type': 'application/json'
  }
});

Upload Methods

The Files API supports two upload methods:

URL Upload

Provide a publicly accessible URL and the file is fetched and stored automatically

Direct Upload

Request a signed URL and upload the file directly from your application

Upload File from URL

Upload a file by providing a publicly accessible URL. The file is streamed directly to storage without buffering, making this efficient for large files. Endpoint: POST /api/v1/files
const response = await fetch('https://api.context.ai/api/v1/files', {
  method: 'POST',
  headers: {
    'Authorization': 'Bearer ctx_your_api_key',
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    url: 'https://yourbucket.s3.amazonaws.com/documents/report.pdf'
  })
});

const result = await response.json();
console.log('File ID:', result.fileId);

Request Body

FieldTypeRequiredDescription
urlstringYesPublicly accessible URL of the file to upload

Response (201 Created)

{
  "fileId": "abc123-def456-ghi789"
}

Supported URL Sources

The URL upload supports files from:
  • Amazon S3 buckets
  • Google Cloud Storage
  • Azure Blob Storage
  • Any publicly accessible HTTPS URL
For security, only HTTPS URLs pointing to public hosts are accepted. Private or internal URLs are blocked.

Request Signed Upload URL

Request a signed URL for direct file upload from your application. This is useful when you have the file content locally and want to upload it directly. Endpoint: POST /api/v1/files
// Step 1: Request a signed upload URL
const response = await fetch('https://api.context.ai/api/v1/files', {
  method: 'POST',
  headers: {
    'Authorization': 'Bearer ctx_your_api_key',
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    fileName: 'quarterly-report.pdf'
  })
});

const { uploadUrl, fileId, storagePath } = await response.json();
console.log('Upload URL:', uploadUrl);
console.log('File ID:', fileId);

Request Body

FieldTypeRequiredDescription
fileNamestringYesName of the file to upload

Response (200 OK)

{
  "uploadUrl": "https://storage.context.ai/upload/signed...",
  "fileId": "abc123-def456-ghi789",
  "storagePath": "tasks-api/team-xyz/1705312200000-quarterly-report.pdf"
}

Upload to Signed URL

After receiving the signed URL, upload the file content directly:
// Step 2: Upload file to the signed URL
const fileContent = await fs.promises.readFile('./quarterly-report.pdf');

const uploadResponse = await fetch(uploadUrl, {
  method: 'PUT',
  body: fileContent,
  headers: {
    'Content-Type': 'application/pdf'
  }
});

if (!uploadResponse.ok) {
  throw new Error('Upload failed');
}

console.log('File uploaded successfully');

Complete Direct Upload

After uploading to the signed URL, call this endpoint to create the file record in the database. Endpoint: POST /api/v1/files/:fileId/complete
// Step 3: Complete the upload
const completeResponse = await fetch(`https://api.context.ai/api/v1/files/${fileId}/complete`, {
  method: 'POST',
  headers: {
    'Authorization': 'Bearer ctx_your_api_key',
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    fileName: 'quarterly-report.pdf',
    mimeType: 'application/pdf',
    size: fileContent.length,
    storagePath: storagePath
  })
});

const result = await completeResponse.json();
console.log('Upload complete:', result.fileId);

Request Body

FieldTypeRequiredDescription
fileNamestringYesOriginal file name
mimeTypestringYesMIME type of the file
sizenumberYesFile size in bytes
storagePathstringYesStorage path returned from the signed URL request

Response (201 Created)

{
  "fileId": "abc123-def456-ghi789"
}

Get File Information

Retrieve file metadata and a signed download URL. Endpoint: GET /api/v1/files/:fileId
const response = await fetch(`https://api.context.ai/api/v1/files/${fileId}`, {
  headers: {
    'Authorization': 'Bearer ctx_your_api_key'
  }
});

const file = await response.json();
console.log('File name:', file.fileName);
console.log('Download URL:', file.url);

Response

{
  "fileId": "abc123-def456-ghi789",
  "fileName": "quarterly-report.pdf",
  "url": "https://storage.context.ai/files/signed...",
  "urlExpiresAt": "2024-01-15T10:40:00.000Z"
}
The signed download URL expires after 10 minutes. Request a new URL if the previous one has expired.

Complete Upload Examples

URL Upload Workflow

The simplest method for files already hosted externally:
class FileUploader {
  constructor(apiKey) {
    this.apiKey = apiKey;
    this.baseUrl = 'https://api.context.ai/api/v1';
  }

  async uploadFromUrl(fileUrl) {
    const response = await fetch(`${this.baseUrl}/files`, {
      method: 'POST',
      headers: {
        'Authorization': `Bearer ${this.apiKey}`,
        'Content-Type': 'application/json'
      },
      body: JSON.stringify({ url: fileUrl })
    });

    if (!response.ok) {
      const error = await response.json();
      throw new Error(error.error || 'Upload failed');
    }

    return response.json();
  }
}

// Usage
const uploader = new FileUploader(process.env.CONTEXT_API_KEY);

const { fileId } = await uploader.uploadFromUrl(
  'https://mybucket.s3.amazonaws.com/reports/q3-financial.pdf'
);

console.log('Uploaded file:', fileId);

Direct Upload Workflow

For uploading files from your local system or application:
const fs = require('fs');
const path = require('path');

class FileUploader {
  constructor(apiKey) {
    this.apiKey = apiKey;
    this.baseUrl = 'https://api.context.ai/api/v1';
  }

  async uploadDirect(filePath) {
    const fileName = path.basename(filePath);
    const fileContent = await fs.promises.readFile(filePath);
    const mimeType = this.getMimeType(fileName);

    // Step 1: Request signed upload URL
    const signedUrlResponse = await fetch(`${this.baseUrl}/files`, {
      method: 'POST',
      headers: {
        'Authorization': `Bearer ${this.apiKey}`,
        'Content-Type': 'application/json'
      },
      body: JSON.stringify({ fileName })
    });

    if (!signedUrlResponse.ok) {
      throw new Error('Failed to get upload URL');
    }

    const { uploadUrl, fileId, storagePath } = await signedUrlResponse.json();

    // Step 2: Upload file to signed URL
    const uploadResponse = await fetch(uploadUrl, {
      method: 'PUT',
      body: fileContent,
      headers: {
        'Content-Type': mimeType
      }
    });

    if (!uploadResponse.ok) {
      throw new Error('Failed to upload file');
    }

    // Step 3: Complete the upload
    const completeResponse = await fetch(`${this.baseUrl}/files/${fileId}/complete`, {
      method: 'POST',
      headers: {
        'Authorization': `Bearer ${this.apiKey}`,
        'Content-Type': 'application/json'
      },
      body: JSON.stringify({
        fileName,
        mimeType,
        size: fileContent.length,
        storagePath
      })
    });

    if (!completeResponse.ok) {
      throw new Error('Failed to complete upload');
    }

    return { fileId, fileName };
  }

  getMimeType(fileName) {
    const ext = path.extname(fileName).toLowerCase();
    const mimeTypes = {
      '.pdf': 'application/pdf',
      '.doc': 'application/msword',
      '.docx': 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
      '.xls': 'application/vnd.ms-excel',
      '.xlsx': 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
      '.ppt': 'application/vnd.ms-powerpoint',
      '.pptx': 'application/vnd.openxmlformats-officedocument.presentationml.presentation',
      '.txt': 'text/plain',
      '.csv': 'text/csv',
      '.json': 'application/json',
      '.png': 'image/png',
      '.jpg': 'image/jpeg',
      '.jpeg': 'image/jpeg',
      '.gif': 'image/gif'
    };
    return mimeTypes[ext] || 'application/octet-stream';
  }
}

// Usage
const uploader = new FileUploader(process.env.CONTEXT_API_KEY);

const { fileId, fileName } = await uploader.uploadDirect('./reports/q3-financial.pdf');
console.log(`Uploaded ${fileName} with ID: ${fileId}`);

Upload Multiple Files

Upload multiple files and use them in a task:
async function uploadFilesAndCreateTask(filePaths, prompt, webhookUrl) {
  const uploader = new FileUploader(process.env.CONTEXT_API_KEY);
  
  // Upload all files in parallel
  const uploadPromises = filePaths.map(filePath => 
    uploader.uploadDirect(filePath)
  );
  
  const uploadResults = await Promise.all(uploadPromises);
  const fileIds = uploadResults.map(result => result.fileId);
  
  console.log('Uploaded files:', fileIds);

  // Create task with all files
  const taskResponse = await fetch('https://api.context.ai/api/v1/tasks', {
    method: 'POST',
    headers: {
      'Authorization': `Bearer ${process.env.CONTEXT_API_KEY}`,
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({
      namespace: 'multi-file-analysis',
      delivery: {
        type: 'webhook',
        config: { endpoint: webhookUrl }
      },
      input: {
        type: 'chat',
        prompt,
        fileIds
      }
    })
  });

  const task = await taskResponse.json();
  console.log('Created task:', task.taskId);
  
  return { fileIds, taskId: task.taskId };
}

// Usage
const result = await uploadFilesAndCreateTask(
  ['./data/q1-report.pdf', './data/q2-report.pdf', './data/q3-report.pdf'],
  'Compare these quarterly reports and identify trends across all three quarters.',
  'https://yourcompany.com/webhooks/context'
);

Error Handling

Error Response Format

{
  "error": "Error description message"
}

HTTP Status Codes

CodeDescription
200Signed upload URL generated successfully
201File uploaded or completed successfully
400Invalid request body or missing required fields
401Missing or invalid API key
404File not found
500Internal server error

Common Errors

ErrorCauseResolution
Invalid bucket URLURL is not HTTPS or points to private hostUse a publicly accessible HTTPS URL
Failed to fetch from bucketRemote file not accessibleVerify the URL is correct and publicly accessible
Missing required fieldsRequest body is incompleteInclude all required fields
Supabase configuration missingServer configuration issueContact support
File not foundInvalid file IDVerify the file ID is correct

Error Handling Example

async function safeUpload(fileUrl) {
  try {
    const response = await fetch('https://api.context.ai/api/v1/files', {
      method: 'POST',
      headers: {
        'Authorization': `Bearer ${process.env.CONTEXT_API_KEY}`,
        'Content-Type': 'application/json'
      },
      body: JSON.stringify({ url: fileUrl })
    });

    if (!response.ok) {
      const error = await response.json();
      
      switch (response.status) {
        case 400:
          console.error('Invalid request:', error.error);
          break;
        case 401:
          console.error('Authentication failed. Check your API key.');
          break;
        case 500:
          console.error('Server error. Please try again later.');
          break;
        default:
          console.error('Upload failed:', error.error);
      }
      
      return null;
    }

    return response.json();
  } catch (networkError) {
    console.error('Network error:', networkError.message);
    return null;
  }
}

Supported File Types

The Files API supports a wide range of file types:
CategoryExtensions
DocumentsPDF, DOC, DOCX, TXT, RTF
SpreadsheetsXLS, XLSX, CSV
PresentationsPPT, PPTX
ImagesPNG, JPG, JPEG, GIF, WEBP
DataJSON, XML
CodeJS, TS, PY, and other source files

Best Practices

Use URL Upload for External Files

When files are already hosted externally, use URL upload to avoid unnecessary data transfer through your servers

Handle Expiring URLs

Download URLs expire after 10 minutes. Request a new URL if needed rather than caching old ones

Validate Before Upload

Validate file size and type before uploading to avoid unnecessary API calls

Use Parallel Uploads

When uploading multiple files, use Promise.all() to upload in parallel for better performance

Next Steps