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.
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
Field Type Required Description urlstring Yes Publicly 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
Field Type Required Description fileNamestring Yes Name 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
Field Type Required Description fileNamestring Yes Original file name mimeTypestring Yes MIME type of the file sizenumber Yes File size in bytes storagePathstring Yes Storage path returned from the signed URL request
Response (201 Created)
{
"fileId" : "abc123-def456-ghi789"
}
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" : "Error description message"
}
HTTP Status Codes
Code Description 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
Error Cause Resolution Invalid bucket URLURL is not HTTPS or points to private host Use a publicly accessible HTTPS URL Failed to fetch from bucketRemote file not accessible Verify the URL is correct and publicly accessible Missing required fieldsRequest body is incomplete Include all required fields Supabase configuration missingServer configuration issue Contact support File not foundInvalid file ID Verify 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:
Category Extensions Documents PDF, DOC, DOCX, TXT, RTF Spreadsheets XLS, XLSX, CSV Presentations PPT, PPTX Images PNG, JPG, JPEG, GIF, WEBP Data JSON, XML Code JS, 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