> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://documents.pyramid-ai.com/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://documents.pyramid-ai.com/_mcp/server.

# Upload & Manage Documents

## Before you begin

* You have an API key (`pai_test_*` or `pai_live_*`)
* You have at least one project created ([Create a Project](/howto/projects))
* Feature `api.documents` is enabled for your organization

## Upload a document (3-step flow)

Document upload uses presigned URLs so your files go directly to storage without passing through the API server.

#### Reserve an upload slot

Tell the API what file you're uploading. You'll get back a presigned URL for direct upload.

```bash
curl -X POST https://api-staging.pyramid-ai.com/api/v2/documents \
  -H "Authorization: Bearer pai_test_YOUR_KEY_HERE" \
  -H "Content-Type: application/json" \
  -d '{
    "file_name": "safety-manual.pdf",
    "content_type": "application/pdf",
    "size_bytes": 2048576,
    "project_id": "YOUR_PROJECT_ID"
  }'
```

```json
{
  "success": true,
  "data": {
    "id": "doc_xyz789",
    "status": "uploading",
    "upload": {
      "url": "https://storage.supabase.co/...",
      "method": "PUT",
      "headers": {
        "Content-Type": "application/pdf"
      },
      "expires_at": "2026-05-20T10:15:00Z"
    }
  },
  "request_id": "..."
}
```

Save the `id` and the `upload.url`.

#### Upload the file to storage

Use the presigned URL from step 1 to upload your file directly. No authorization header needed — the URL itself is the grant.

```bash
curl -X PUT "PRESIGNED_URL_FROM_STEP_1" \
  -H "Content-Type: application/pdf" \
  --data-binary @safety-manual.pdf
```

> **Note**
>
> The presigned URL expires after 15 minutes. If it expires, reserve a new upload slot.

#### Trigger processing

Once the file is uploaded, tell the API to start processing it into searchable knowledge.

```bash
curl -X POST https://api-staging.pyramid-ai.com/api/v2/documents/process \
  -H "Authorization: Bearer pai_test_YOUR_KEY_HERE" \
  -H "Content-Type: application/json" \
  -d '{"document_ids": ["doc_xyz789"]}'
```

You can pass multiple document IDs to process several files at once.

## Check document status

After triggering processing, poll the document to track its progress:

```bash
curl https://api-staging.pyramid-ai.com/api/v2/documents/doc_xyz789 \
  -H "Authorization: Bearer pai_test_YOUR_KEY_HERE"
```

```json
{
  "success": true,
  "data": {
    "id": "doc_xyz789",
    "file_name": "safety-manual.pdf",
    "status": "ready",
    "project_id": "YOUR_PROJECT_ID",
    "created_at": "2026-05-20T10:00:00Z"
  },
  "request_id": "..."
}
```

Document status progresses through: `uploading` → `uploaded` → `processing` → `ready`. A document is queryable once it reaches `ready`.

## List documents

```bash
# All documents in a project
curl "https://api-staging.pyramid-ai.com/api/v2/documents?project_id=YOUR_PROJECT_ID" \
  -H "Authorization: Bearer pai_test_YOUR_KEY_HERE"

# Filter by status
curl "https://api-staging.pyramid-ai.com/api/v2/documents?project_id=YOUR_PROJECT_ID&status=ready" \
  -H "Authorization: Bearer pai_test_YOUR_KEY_HERE"
```

## Delete documents

Remove one or more documents in a single call:

```bash
curl -X DELETE https://api-staging.pyramid-ai.com/api/v2/documents \
  -H "Authorization: Bearer pai_test_YOUR_KEY_HERE" \
  -H "Content-Type: application/json" \
  -d '{"document_ids": ["doc_xyz789"]}'
```

This removes the document, its storage file, and all associated chunks and embeddings.

## What's next

* [Ask a Question](/howto/agent) — query documents using Pyramid Agent
* [Run a Compliance Check](/howto/check) — verify requirements against your documents