> ## Documentation Index
> Fetch the complete documentation index at: https://docs.raydocs.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Create Document

> Create/reuse workspace documents from upload keys and attach them to a session.

<Note>
  This endpoint is **Step 3** of a 3-step upload process. Files must first be uploaded to temporary storage via signed URL before being associated with a session. See the [complete upload guide](/api-reference/cookbook/uploading-documents) for the full flow.
</Note>

## How It Works

This endpoint handles **upload attach**: create or reuse workspace documents from uploaded key(s).
To attach already existing documents, use `POST /extractions/sessions/{sessionId}/documents/attach`.

```mermaid theme={null}
sequenceDiagram
    participant Client
    participant API
    participant S3

    Client->>API: 1. POST /vapor/signed-storage-url
    API->>Client: Signed S3 URL + file key
    Client->>S3: 2. PUT file to signed URL
    S3->>Client: Upload confirmed
    Client->>API: 3. POST /sessions/{id}/documents/upload (this endpoint)
    API->>Client: Document record created
```

## Authentication & Scope

Requires the `sessions-write` ability.

## Request

This endpoint expects JSON (not binary upload).

```http theme={null}
POST /extractions/sessions/770e8400-e29b-41d4-a716-446655440000/documents/upload HTTP/1.1
Host: api.raydocs.com
Authorization: Bearer <token>
Content-Type: application/json

{
  "keys": ["tmp/721c7d17-f810-41a8-8c1c-a7e8cd2e52d0"]
}
```

### Path Parameters

| Parameter   | Type | Required | Description    |
| ----------- | ---- | -------- | -------------- |
| `sessionId` | uuid | Yes      | The session ID |

### Body Parameters

| Parameter | Type           | Required | Description                          |
| --------- | -------------- | -------- | ------------------------------------ |
| `keys`    | array\[string] | Yes      | Upload key list from signed URL flow |

### Supported Formats

* PDF (`.pdf`)
* Microsoft Word (`.docx`, `.doc`)
* Images (`.png`, `.jpg`, `.jpeg`, `.tiff`)
* PowerPoint (`.pptx`)

## Response

`200 OK` – Documents attached.

```json theme={null}
{
  "data": [
    {
      "id": "880e8400-e29b-41d4-a716-446655440000",
      "workspace_id": "660e8400-e29b-41d4-a716-446655440000",
      "filename": "invoice.pdf",
      "sha256": "6de7f6f5894c9f3fd1f6f8a4d1b3115d0d9b4b19d7a8a661f9fe90f9c2d80c3b",
      "status": "uploaded",
      "created_at": "2024-01-15T10:30:00Z"
    }
  ]
}
```

<Check>
  Upload/import is storage-only. Parsing is requested explicitly (reparse endpoint) or at extraction run time when required.
</Check>

<Note>
  Deduplication is content-based at workspace scope. If uploaded bytes match an existing document (`sha256`), the API reuses that document and only creates the session attachment.
</Note>

`422 Unprocessable Entity` – Invalid key or unsupported file format.

## Quick Reference: Complete Upload Flow

<Steps>
  <Step title="Get signed upload URL">
    ```bash theme={null}
    curl -X POST 'https://api.raydocs.com/vapor/signed-storage-url' \
      -H 'Authorization: Bearer <token>' \
      -H 'Content-Type: application/json' \
      -d '{"visibility": "private"}'
    ```

    Returns `url`, `key`, and `headers` for the S3 upload.
  </Step>

  <Step title="Upload file to S3">
    ```bash theme={null}
    curl -X PUT "${SIGNED_URL}" \
      -H 'Content-Type: application/pdf' \
      --data-binary @invoice.pdf
    ```
  </Step>

  <Step title="Create document record (this endpoint)">
    ```bash theme={null}
    curl -X POST 'https://api.raydocs.com/extractions/sessions/{sessionId}/documents/upload' \
      -H 'Authorization: Bearer <token>' \
      -H 'Content-Type: application/json' \
      -d '{"keys": ["tmp/abc123-..."]}'
    ```
  </Step>
</Steps>

<Tip>
  For detailed code examples in JavaScript and Python, see the [Uploading Documents cookbook](/api-reference/cookbook/uploading-documents).
</Tip>


## OpenAPI

````yaml post /extractions/sessions/{sessionId}/documents/upload
openapi: 3.0.1
info:
  title: Raydocs API
  description: REST API for document extraction with AI-powered data parsing
  version: 1.0.0
servers:
  - url: https://api.raydocs.com
security:
  - bearerAuth: []
tags:
  - name: Workspaces
    description: Create and manage workspaces.
  - name: Workspace Users
    description: Manage users within a workspace.
  - name: Extraction Templates
    description: Define extraction schemas and settings.
  - name: Extraction Sessions
    description: Manage extraction jobs and documents.
  - name: Batch Operations
    description: Bulk operations on sessions.
  - name: Documents
    description: Upload and manage source documents.
  - name: Workflows
    description: Discover workflow runs and read their public outputs.
  - name: Results
    description: Access extraction results.
paths:
  /extractions/sessions/{sessionId}/documents/upload:
    post:
      tags:
        - Extraction Sessions
      summary: Upload Session Documents
      description: >-
        Create/reuse workspace documents from upload keys and attach them to the
        session. Requires `sessions-write`.
      operationId: uploadSessionDocuments
      parameters:
        - name: sessionId
          in: path
          required: true
          schema:
            type: string
            format: uuid
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - keys
              properties:
                keys:
                  type: array
                  description: >-
                    Temporary upload keys returned by
                    `/vapor/signed-storage-url`
                  items:
                    type: string
      responses:
        '200':
          description: Documents attached
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      $ref: '#/components/schemas/Document'
        '403':
          description: Forbidden
        '422':
          description: Validation error
components:
  schemas:
    Document:
      type: object
      properties:
        id:
          type: string
          format: uuid
          readOnly: true
        workspace_id:
          type: integer
        filename:
          type: string
        mime:
          type: string
        size:
          type: integer
          description: File size in bytes
        sha256:
          type: string
          minLength: 64
          maxLength: 64
        status:
          type: string
          enum:
            - uploaded
            - queued
            - parsing
            - parsed
            - processed
            - failed
        source_type:
          type: string
          enum:
            - upload
            - url
            - connector
        source_url:
          type: string
          nullable: true
        parsings:
          type: array
          items:
            $ref: '#/components/schemas/DocumentParsingSummary'
        created_at:
          type: string
          format: date-time
          readOnly: true
    DocumentParsingSummary:
      type: object
      properties:
        id:
          type: string
          format: uuid
        config_hash:
          type: string
        status:
          type: string
          enum:
            - queued
            - processing
            - ready
            - failed
        parser_version:
          type: string
        updated_at:
          type: string
          format: date-time
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      description: >
        Personal Access Token created from the Raydocs dashboard.

        Include in the Authorization header: `Bearer <your_token>`

        See [API Keys](/api-reference/api-keys) for token creation and
        management.

````