# Files API

The Files API manages stored PDFs in the workspace bound to your API key or OAuth connection. It can list and search documents, issue fresh download URLs, return PDF binaries, and delete files.

In the [workspace release](https://pdf-mcp.io/docs/workspaces), consumers and editors can access only their own files. Admins can access all files in that workspace, including retained files from removed members. These rules also cover search snippets, counts, and document IDs supplied as inputs to other PDF tools. An admin's new output belongs to that admin. Dashboard switching does not change an integration's workspace.

## Overview

PDFs generated with `storage: {"mode": "default"}` or `storage: {"mode": "byob"}` are stored and tracked in the bound workspace. Omitted storage options follow workspace defaults. The Files API can:

- List stored documents with pagination and filtering
- Search document contents with full-text or substring matching
- Retrieve a document with a fresh presigned download URL
- Download a PDF binary when a presigned URL is not accessible
- Delete a document from storage

---

## List files

Retrieve a paginated list of accessible stored documents in the bound workspace.

### Endpoint

```
GET /files
```

### Authentication

Send a valid API key or OAuth token in the `Authorization` header:

```
Authorization: Bearer YOUR_API_KEY
```

See [Authentication](https://pdf-mcp.io/docs/authentication) for details.

### Query parameters

| Parameter | Type | Required | Default | Description |
|-----------|------|----------|---------|-------------|
| `limit` | integer | No | 50 | Maximum documents to return (max: 100) |
| `offset` | integer | No | 0 | Number of documents to skip for pagination |
| `storage_mode` | string | No | - | Filter by storage mode: `default` or `byob` |

### Request example

```bash
# List first 50 documents
curl -X GET "https://api.pdf-mcp.io/files" \
  -H "Authorization: Bearer YOUR_API_KEY"

# List with pagination
curl -X GET "https://api.pdf-mcp.io/files?limit=20&offset=40" \
  -H "Authorization: Bearer YOUR_API_KEY"

# Filter by storage mode
curl -X GET "https://api.pdf-mcp.io/files?storage_mode=default" \
  -H "Authorization: Bearer YOUR_API_KEY"
```

### Success response

```json
{
  "documents": [
    {
      "id": "550e8400-e29b-41d4-a716-446655440000",
      "filename": "invoice-2024.pdf",
      "storage_mode": "default",
      "file_size_bytes": 45678,
      "page_count": 3,
      "source_endpoint": "/htmlToPdf",
      "url": "https://s3.eu-central-1.amazonaws.com/...",
      "signed_url_expires_at": "2024-01-15T12:00:00Z",
      "expires_at": "2024-02-15T10:30:00Z",
      "created_at": "2024-01-15T10:30:00Z"
    }
  ],
  "total": 150,
  "limit": 50,
  "offset": 0
}
```

### Response fields

| Field | Type | Description |
|-------|------|-------------|
| `documents` | array | Array of document objects |
| `total` | integer | Total number of documents matching filter |
| `limit` | integer | Limit used for this request |
| `offset` | integer | Offset used for this request |

### Document object

| Field | Type | Description |
|-------|------|-------------|
| `id` | string | Document UUID |
| `workspace_id` | string | Workspace containing the document |
| `owner_user_id` | string or null | Original file owner; may be null after account deletion |
| `filename` | string | Document filename |
| `storage_mode` | string | `default` or `byob` |
| `file_size_bytes` | integer | Size of the PDF in bytes |
| `page_count` | integer | Number of pages |
| `source_endpoint` | string | API endpoint that generated the PDF |
| `url` | string | Presigned URL for downloading |
| `signed_url_expires_at` | string | Expiration time of the signed URL (ISO 8601) |
| `expires_at` | string | Auto-deletion timestamp if set (ISO 8601) |
| `created_at` | string | Document creation timestamp (ISO 8601) |

### Status codes

| Code | Description |
|------|-------------|
| 200 | Success - Documents list returned |
| 401 | Unauthorized - Missing or invalid Authorization header |
| 500 | Internal Server Error - Failed to list documents |

### Credit usage

**Free** (0 credits)

---

## Search files

Search document contents using full-text search or substring matching.

### Endpoint

```
GET /files/search
```

### Authentication

Send a valid API key or OAuth token in the `Authorization` header:

```
Authorization: Bearer YOUR_API_KEY
```

See [Authentication](https://pdf-mcp.io/docs/authentication) for details.

### Query parameters

| Parameter | Type | Required | Default | Description |
|-----------|------|----------|---------|-------------|
| `q` | string | Yes | - | Search query string |
| `mode` | string | No | `fulltext` | Search mode: `fulltext` or `grep` |
| `limit` | integer | No | 20 | Maximum results to return (max: 100) |

### Search modes

**fulltext** (default)
- Uses PostgreSQL full-text search
- Returns results ranked by relevance
- Supports word stemming and language-aware matching
- Faster for large document collections
- Returns snippets with match context

**grep**
- Case-insensitive substring matching
- Exact phrase matching
- Slower than fulltext, especially for large collections
- No relevance ranking
- Returns snippets with match context

### Request example

```bash
# Full-text search
curl -X GET "https://api.pdf-mcp.io/files/search?q=invoice%20total" \
  -H "Authorization: Bearer YOUR_API_KEY"

# Grep mode for exact substring
curl -X GET "https://api.pdf-mcp.io/files/search?q=INV-2024-001&mode=grep" \
  -H "Authorization: Bearer YOUR_API_KEY"

# Limit results
curl -X GET "https://api.pdf-mcp.io/files/search?q=contract&limit=10" \
  -H "Authorization: Bearer YOUR_API_KEY"
```

### Success response

```json
{
  "results": [
    {
      "document": {
        "id": "550e8400-e29b-41d4-a716-446655440000",
        "filename": "invoice-2024.pdf",
        "storage_mode": "default",
        "file_size_bytes": 45678,
        "page_count": 3,
        "source_endpoint": "/htmlToPdf",
        "url": "https://s3.eu-central-1.amazonaws.com/...",
        "signed_url_expires_at": "2024-01-15T12:00:00Z",
        "expires_at": "2024-02-15T10:30:00Z",
        "created_at": "2024-01-15T10:30:00Z"
      },
      "rank": 0.85,
      "snippet": "...total amount due: $1,234.56. Invoice date..."
    }
  ],
  "total": 5,
  "query": "invoice total",
  "mode": "fulltext"
}
```

### Response fields

| Field | Type | Description |
|-------|------|-------------|
| `results` | array | Array of search hit objects |
| `total` | integer | Total number of matching documents |
| `query` | string | The search query used |
| `mode` | string | The search mode used |

### Search result object

| Field | Type | Description |
|-------|------|-------------|
| `document` | object | Document metadata with presigned URL |
| `rank` | number | Relevance score (fulltext mode only, null for grep) |
| `snippet` | string | Text snippet showing match context |

### Status codes

| Code | Description |
|------|-------------|
| 200 | Success - Search results returned |
| 400 | Bad Request - Missing query or invalid mode |
| 401 | Unauthorized - Missing or invalid Authorization header |
| 500 | Internal Server Error - Search failed |

### Credit usage

**0.01 credits** per search

### Notes

- Search is performed on the markdown representation of PDF content extracted during generation
- Documents without text content (e.g., image-based PDFs) will not appear in search results
- Consumers and editors search their own files; admins search all files in the bound workspace

---

## Get a file

Retrieve a single document by ID with a fresh presigned download URL.

### Endpoint

```
GET /files/{document_id}
```

### Authentication

Send a valid API key or OAuth token in the `Authorization` header:

```
Authorization: Bearer YOUR_API_KEY
```

See [Authentication](https://pdf-mcp.io/docs/authentication) for details.

### Path parameters

| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `document_id` | string | Yes | UUID of the document to retrieve |

### Query parameters

| Parameter | Type | Required | Default | Description |
|-----------|------|----------|---------|-------------|
| `expires_in` | integer | No | 300 effective | Signed URL lifetime in seconds; clamped to 60-300 |

### Request example

```bash
# Get document with a fresh five-minute URL
curl -X GET "https://api.pdf-mcp.io/files/550e8400-e29b-41d4-a716-446655440000" \
  -H "Authorization: Bearer YOUR_API_KEY"

# Request a shorter one-minute URL
curl -X GET "https://api.pdf-mcp.io/files/550e8400-e29b-41d4-a716-446655440000?expires_in=60" \
  -H "Authorization: Bearer YOUR_API_KEY"

# Explicitly request the maximum delivered lifetime
curl -X GET "https://api.pdf-mcp.io/files/550e8400-e29b-41d4-a716-446655440000?expires_in=300" \
  -H "Authorization: Bearer YOUR_API_KEY"
```

### Success response

```json
{
  "id": "550e8400-e29b-41d4-a716-446655440000",
  "filename": "invoice-2024.pdf",
  "storage_mode": "default",
  "file_size_bytes": 45678,
  "page_count": 3,
  "source_endpoint": "/htmlToPdf",
  "url": "https://s3.eu-central-1.amazonaws.com/...",
  "signed_url_expires_at": "2024-01-15T12:00:00Z",
  "expires_at": "2024-02-15T10:30:00Z",
  "created_at": "2024-01-15T10:30:00Z"
}
```

### Response fields

| Field | Type | Description |
|-------|------|-------------|
| `id` | string | Document UUID |
| `filename` | string | Document filename |
| `storage_mode` | string | `default` or `byob` |
| `file_size_bytes` | integer | Size of the PDF in bytes |
| `page_count` | integer | Number of pages |
| `source_endpoint` | string | API endpoint that generated the PDF |
| `url` | string | Fresh presigned URL for downloading |
| `signed_url_expires_at` | string | Expiration time of the signed URL (ISO 8601) |
| `expires_at` | string | Auto-deletion timestamp if set (ISO 8601) |
| `created_at` | string | Document creation timestamp (ISO 8601) |

### Status codes

| Code | Description |
|------|-------------|
| 200 | Success - Document returned with presigned URL |
| 401 | Unauthorized - Missing or invalid Authorization header |
| 403 | Forbidden - Workspace membership, role, or file access denied |
| 404 | Not Found - Document not found or was deleted |
| 502 | Bad Gateway - Failed to generate download URL |

### Credit usage

**Free** (0 credits)

---

## Download a file

Download a PDF binary by document ID. The endpoint proxies the file from S3 and returns the PDF instead of a presigned URL.

### Endpoint

```
GET /files/{document_id}/download
```

### Authentication

Send a valid API key or OAuth token in the `Authorization` header:

```
Authorization: Bearer YOUR_API_KEY
```

See [Authentication](https://pdf-mcp.io/docs/authentication) for details.

### Path parameters

| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `document_id` | string | Yes | UUID of the document to download |

### Request example

```bash
# Download PDF directly
curl -X GET "https://api.pdf-mcp.io/files/550e8400-e29b-41d4-a716-446655440000/download" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  --output document.pdf
```

### Success response

Returns the raw PDF binary with the following headers:

| Header | Value |
|--------|-------|
| `Content-Type` | `application/pdf` |
| `Content-Disposition` | `attachment; filename="original-filename.pdf"` |
| `Content-Length` | File size in bytes |

### Status codes

| Code | Description |
|------|-------------|
| 200 | Success - PDF binary returned |
| 401 | Unauthorized - Missing or invalid Authorization header |
| 403 | Forbidden - Workspace membership, role, or file access denied |
| 404 | Not Found - Document not found or was deleted |
| 502 | Bad Gateway - Failed to download file from storage |

### Credit usage

**Free** (0 credits)

### Notes

- Returns the actual PDF bytes, not a JSON response with a presigned URL
- Useful when your environment cannot access S3 presigned URLs directly (e.g., firewalled VMs, restricted networks)
- The original filename is preserved in the `Content-Disposition` header
- The document owner or an admin of its workspace can download it

---

## Delete a file

Delete a document by ID, removing it from storage.

### Endpoint

```
DELETE /files/{document_id}
```

### Authentication

Send a valid API key or OAuth token in the `Authorization` header:

```
Authorization: Bearer YOUR_API_KEY
```

See [Authentication](https://pdf-mcp.io/docs/authentication) for details.

### Path parameters

| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `document_id` | string | Yes | UUID of the document to delete |

### Request example

```bash
curl -X DELETE "https://api.pdf-mcp.io/files/550e8400-e29b-41d4-a716-446655440000" \
  -H "Authorization: Bearer YOUR_API_KEY"
```

### Success response

```json
{
  "deleted": true,
  "document_id": "550e8400-e29b-41d4-a716-446655440000",
  "message": "Document 550e8400-e29b-41d4-a716-446655440000 has been deleted"
}
```

### Response fields

| Field | Type | Description |
|-------|------|-------------|
| `deleted` | boolean | True if deletion succeeded |
| `document_id` | string | UUID of the deleted document |
| `message` | string | Confirmation message |

### Status codes

| Code | Description |
|------|-------------|
| 200 | Success - Document deleted |
| 401 | Unauthorized - Missing or invalid Authorization header |
| 403 | Forbidden - Workspace membership, role, or file access denied |
| 404 | Not Found - Document not found or was already deleted |
| 502 | Bad Gateway - Failed to delete file from storage |

### Credit usage

**Free** (0 credits)

### Notes

- Deletion is soft: document metadata keeps a `deleted_at` timestamp but no longer appears in list queries
- The actual file is removed from S3 storage
- This action cannot be undone

---

## Examples

### List recent documents

Retrieve the most recent documents for display in a dashboard:

```bash
curl -X GET "https://api.pdf-mcp.io/files?limit=10" \
  -H "Authorization: Bearer YOUR_API_KEY"
```

### Paginate through documents

Retrieve all documents in batches:

```bash
# First page
curl -X GET "https://api.pdf-mcp.io/files?limit=50&offset=0" \
  -H "Authorization: Bearer YOUR_API_KEY"

# Second page
curl -X GET "https://api.pdf-mcp.io/files?limit=50&offset=50" \
  -H "Authorization: Bearer YOUR_API_KEY"

# Continue until total is reached...
```

### Find documents by content

Search for invoices containing a specific customer name:

```bash
curl -X GET "https://api.pdf-mcp.io/files/search?q=Acme%20Corporation" \
  -H "Authorization: Bearer YOUR_API_KEY"
```

### Find an exact reference

Search for a specific invoice number using grep mode:

```bash
curl -X GET "https://api.pdf-mcp.io/files/search?q=INV-2024-00123&mode=grep" \
  -H "Authorization: Bearer YOUR_API_KEY"
```

### Get a fresh download URL

Retrieve a document with a custom expiry time for sharing:

```bash
# Get a fresh five-minute download link
curl -X GET "https://api.pdf-mcp.io/files/550e8400-e29b-41d4-a716-446655440000?expires_in=300" \
  -H "Authorization: Bearer YOUR_API_KEY"
```

### Download a PDF directly

Download the PDF file when presigned URLs are not accessible:

```bash
curl -X GET "https://api.pdf-mcp.io/files/550e8400-e29b-41d4-a716-446655440000/download" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  --output invoice.pdf
```

### Delete old documents

Delete documents that are no longer needed:

```bash
curl -X DELETE "https://api.pdf-mcp.io/files/550e8400-e29b-41d4-a716-446655440000" \
  -H "Authorization: Bearer YOUR_API_KEY"
```

---

## Implementation notes

### Pagination

- Use reasonable page sizes (20-50 documents) for better performance
- Cache the `total` count to calculate total pages without re-fetching
- Consider filtering by `storage_mode` if you have documents in both modes

### Search

- Use **fulltext** mode for natural language queries (e.g., "invoice payment due")
- Use **grep** mode for exact identifiers (e.g., "INV-2024-001", email addresses)
- Keep search queries focused - broader queries return more results but may be less relevant

### Signed URLs

- Presigned URLs expire - always check `signed_url_expires_at` before using
- Delivered links are capped at five minutes (300 seconds); request a fresh link through an authenticated endpoint after expiry
- Presigned S3 links are bearer capabilities and can remain usable until expiry even after membership removal. Keep them private.

### Storage

- Documents with `expires_at` set will be automatically deleted
- Manually delete documents you no longer need to free up storage
- Use search to find old or unused documents for cleanup

---

## Related endpoints

- [HTML to PDF](https://pdf-mcp.io/docs/api-html-to-pdf): generate a stored PDF from HTML
- [Text to PDF](https://pdf-mcp.io/docs/api-text-to-pdf): generate a stored PDF from text
- [Image to PDF](https://pdf-mcp.io/docs/api-image-to-pdf): generate a stored PDF from images

## Credit summary

| Endpoint | Credits |
|----------|---------|
| GET /files | Free |
| GET /files/search | 0.01 |
| GET /files/{id} | Free |
| GET /files/{id}/download | Free |
| DELETE /files/{id} | Free |
