# Files API (Beta)

The Files API allows you to upload, manage, and download files for use with Claude. Files can be referenced in messages for document analysis, image processing, and other file-based operations.

## Overview

The Files API enables:
- Upload files for use in conversations
- Manage uploaded files (list, retrieve metadata, delete)
- Download files when needed
- Reference files across multiple messages
- Support for images and documents (PDFs)

**Beta Feature**: Requires `betas: ['files-api-2025-04-14']`

## API Reference

```typescript { .api }
class Files extends APIResource {
  upload(params: FileUploadParams): APIPromise<FileMetadata>;
  list(params?: FileListParams): FileMetadataPage;
  retrieveMetadata(fileID: string, params?: FileRetrieveMetadataParams): APIPromise<FileMetadata>;
  download(fileID: string, params?: FileDownloadParams): APIPromise<Response>;
  delete(fileID: string, params?: FileDeleteParams): APIPromise<DeletedFile>;
}
```

Access via:

```typescript
client.beta.files.*
```

## File Types

```typescript { .api }
interface FileMetadata {
  id: string;
  type: 'file';
  filename: string;
  size: number;  // Bytes
  created_at: string;  // ISO 8601
}

interface DeletedFile {
  id: string;
  type: 'file';
  deleted: boolean;
}
```

## Uploading Files

```typescript { .api }
client.beta.files.upload(
  params: FileUploadParams
): APIPromise<FileMetadata>;

interface FileUploadParams {
  file: File | Blob | ReadStream;
  betas: ['files-api-2025-04-14'];
}
```

**Example - Node.js:**

```typescript
import Anthropic, { toFile } from '@anthropic-ai/sdk';
import fs from 'fs';

const client = new Anthropic();

// Upload from file system
const file = await client.beta.files.upload({
  file: await toFile(
    fs.createReadStream('/path/to/document.pdf'),
    'document.pdf',
    { type: 'application/pdf' }
  ),
  betas: ['files-api-2025-04-14'],
});

console.log('File ID:', file.id);
console.log('Filename:', file.filename);
console.log('Size:', file.size, 'bytes');
```

**Example - Browser:**

```typescript
// Upload from File input
const fileInput = document.querySelector('input[type="file"]');
const uploadedFile = fileInput.files[0];

const file = await client.beta.files.upload({
  file: uploadedFile,
  betas: ['files-api-2025-04-14'],
});
```

**Example - Buffer:**

```typescript
import { toFile } from '@anthropic-ai/sdk';

const buffer = Buffer.from('PDF content here...');

const file = await client.beta.files.upload({
  file: await toFile(buffer, 'document.pdf', { type: 'application/pdf' }),
  betas: ['files-api-2025-04-14'],
});
```

**Example - Fetch Response:**

```typescript
const response = await fetch('https://example.com/document.pdf');

const file = await client.beta.files.upload({
  file: response,
  betas: ['files-api-2025-04-14'],
});
```

## Using Uploaded Files

Reference uploaded files in messages:

```typescript
// Upload file first
const file = await client.beta.files.upload({
  file: await toFile(fs.createReadStream('report.pdf'), 'report.pdf', { type: 'application/pdf' }),
  betas: ['files-api-2025-04-14'],
});

// Use file in message
const message = await client.beta.messages.create({
  model: 'claude-sonnet-4-5-20250929',
  max_tokens: 2048,
  betas: ['files-api-2025-04-14'],
  messages: [
    {
      role: 'user',
      content: [
        {
          type: 'document',
          source: {
            type: 'file',
            file_id: file.id,  // Reference uploaded file
          },
        },
        {
          type: 'text',
          text: 'Summarize this document.',
        },
      ],
    },
  ],
});
```

For images:

```typescript
const image = await client.beta.files.upload({
  file: await toFile(fs.createReadStream('photo.jpg'), 'photo.jpg', { type: 'image/jpeg' }),
  betas: ['files-api-2025-04-14'],
});

const message = await client.beta.messages.create({
  model: 'claude-sonnet-4-5-20250929',
  max_tokens: 1024,
  betas: ['files-api-2025-04-14'],
  messages: [
    {
      role: 'user',
      content: [
        {
          type: 'image',
          source: {
            type: 'file',
            file_id: image.id,
          },
        },
        {
          type: 'text',
          text: 'What is in this image?',
        },
      ],
    },
  ],
});
```

## Listing Files

```typescript { .api }
client.beta.files.list(
  params?: FileListParams
): FileMetadataPage;

interface FileListParams {
  before_id?: string;
  after_id?: string;
  limit?: number;  // Default: 20
  betas: ['files-api-2025-04-14'];
}
```

**Example:**

```typescript
const files = await client.beta.files.list({
  limit: 50,
  betas: ['files-api-2025-04-14'],
});

for (const file of files.data) {
  console.log(`${file.filename} - ${file.size} bytes - ${file.created_at}`);
}

// Auto-pagination
for await (const file of client.beta.files.list({ betas: ['files-api-2025-04-14'] })) {
  console.log(file.id);
}
```

## Retrieving File Metadata

```typescript { .api }
client.beta.files.retrieveMetadata(
  fileID: string,
  params?: FileRetrieveMetadataParams
): APIPromise<FileMetadata>;

interface FileRetrieveMetadataParams {
  betas: ['files-api-2025-04-14'];
}
```

**Example:**

```typescript
const metadata = await client.beta.files.retrieveMetadata('file_abc123', {
  betas: ['files-api-2025-04-14'],
});

console.log('Filename:', metadata.filename);
console.log('Size:', metadata.size);
console.log('Created:', metadata.created_at);
```

## Downloading Files

```typescript { .api }
client.beta.files.download(
  fileID: string,
  params?: FileDownloadParams
): APIPromise<Response>;

interface FileDownloadParams {
  betas: ['files-api-2025-04-14'];
}
```

**Example:**

```typescript
import fs from 'fs';
import { pipeline } from 'stream/promises';

const response = await client.beta.files.download('file_abc123', {
  betas: ['files-api-2025-04-14'],
});

// Save to file system (Node.js)
await pipeline(
  response.body,
  fs.createWriteStream('/path/to/downloaded-file.pdf')
);

// Or get as buffer
const buffer = Buffer.from(await response.arrayBuffer());

// Browser: Trigger download
const blob = await response.blob();
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = 'file.pdf';
a.click();
```

## Deleting Files

```typescript { .api }
client.beta.files.delete(
  fileID: string,
  params?: FileDeleteParams
): APIPromise<DeletedFile>;

interface FileDeleteParams {
  betas: ['files-api-2025-04-14'];
}
```

**Example:**

```typescript
const deleted = await client.beta.files.delete('file_abc123', {
  betas: ['files-api-2025-04-14'],
});

console.log('Deleted:', deleted.deleted); // true
```

## Complete Workflow

```typescript
import Anthropic, { toFile } from '@anthropic-ai/sdk';
import fs from 'fs';

const client = new Anthropic();

// 1. Upload file
console.log('Uploading file...');
const file = await client.beta.files.upload({
  file: await toFile(
    fs.createReadStream('document.pdf'),
    'document.pdf',
    { type: 'application/pdf' }
  ),
  betas: ['files-api-2025-04-14'],
});

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

// 2. Use in message
console.log('Creating message...');
const message = await client.beta.messages.create({
  model: 'claude-sonnet-4-5-20250929',
  max_tokens: 2048,
  betas: ['files-api-2025-04-14'],
  messages: [
    {
      role: 'user',
      content: [
        {
          type: 'document',
          source: {
            type: 'file',
            file_id: file.id,
          },
        },
        {
          type: 'text',
          text: 'Extract the key points from this document.',
        },
      ],
    },
  ],
});

console.log('Response:', message.content[0].text);

// 3. Cleanup
console.log('Cleaning up...');
await client.beta.files.delete(file.id, {
  betas: ['files-api-2025-04-14'],
});

console.log('Done!');
```

## File Reuse

Files can be referenced multiple times:

```typescript
const file = await client.beta.files.upload({ /* ... */ });

// Use in multiple messages
const message1 = await client.beta.messages.create({
  model: 'claude-sonnet-4-5-20250929',
  max_tokens: 1024,
  betas: ['files-api-2025-04-14'],
  messages: [{
    role: 'user',
    content: [
      { type: 'document', source: { type: 'file', file_id: file.id } },
      { type: 'text', text: 'Summarize this.' },
    ],
  }],
});

const message2 = await client.beta.messages.create({
  model: 'claude-sonnet-4-5-20250929',
  max_tokens: 1024,
  betas: ['files-api-2025-04-14'],
  messages: [{
    role: 'user',
    content: [
      { type: 'document', source: { type: 'file', file_id: file.id } },
      { type: 'text', text: 'What are the main topics?' },
    ],
  }],
});

// Cleanup when done
await client.beta.files.delete(file.id, { betas: ['files-api-2025-04-14'] });
```

## Supported File Types

### Documents
- PDF: `application/pdf`
- Text: `text/plain`

### Images
- JPEG: `image/jpeg`
- PNG: `image/png`
- GIF: `image/gif`
- WebP: `image/webp`

## Limitations

- Maximum file size varies by type
- Files are stored temporarily
- Access requires beta header
- Automatic cleanup after expiration

## Best Practices

### File Management

```typescript
// ✅ Good: Clean up after use
const file = await client.beta.files.upload({ /* ... */ });
try {
  const message = await client.beta.messages.create({ /* ... */ });
  // Use message
} finally {
  await client.beta.files.delete(file.id, { betas: ['files-api-2025-04-14'] });
}

// ❌ Bad: Leaving files around
const file = await client.beta.files.upload({ /* ... */ });
const message = await client.beta.messages.create({ /* ... */ });
// File never deleted
```

### Error Handling

```typescript
try {
  const file = await client.beta.files.upload({ /* ... */ });
} catch (error) {
  if (error instanceof Anthropic.BadRequestError) {
    console.error('Invalid file:', error.message);
  } else if (error instanceof Anthropic.RateLimitError) {
    console.error('Rate limited, retry later');
  }
  throw error;
}
```

### File Validation

```typescript
// ✅ Good: Validate before upload
async function uploadFile(filePath: string) {
  const stats = await fs.promises.stat(filePath);

  if (stats.size > 10 * 1024 * 1024) { // 10MB
    throw new Error('File too large');
  }

  const ext = path.extname(filePath);
  if (!['.pdf', '.jpg', '.png'].includes(ext)) {
    throw new Error('Unsupported file type');
  }

  return client.beta.files.upload({ /* ... */ });
}
```

## See Also

- [Messages API](./messages.md) - Using files in messages
- [Beta Features](./beta-features.md) - Other beta capabilities
- [Types](./types.md) - File type definitions
