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

# Upload a file

> This endpoint initiates an upload session and returns an `uploadUrl` for the session. Upload your file content using PUT requests to the returned `uploadUrl`. The file will be processed in the background and indexed into your knowledge base once the upload is complete.

```
curl -i -X PUT --data-binary @test.txt "$URL"
```
The resumable uploads use Google Cloud Storage - for more detailed documentation on how to perform the upload step (once you have generated the upload URL) see the [Google Cloud Storage documentation](https://cloud.google.com/storage/docs/resumable-upload).

Pass an optional `id` in the request body to upsert a previously uploaded document. A subsequent call with the same `id` overwrites the existing document once the new upload finishes processing. Each call still returns a fresh `uploadUrl`, so concurrent uploads to the same `id` do not clobber each other in storage (the last one to finish wins).

This endpoint requires a Data Source ID. To get started:

1. Go to the <a href='/admin/connect'>Connectors page</a>
2. Create a new API Connector
3. Copy the data source ID from the connector details page
4. Use this ID in the {data_source_id} path parameter

### Rate Limits

600 requests per minute.

These endpoints require a custom API data source. See [Custom API](/admin/data-sources/custom-api) for setup instructions.

This endpoint returns an `uploadUrl`. Upload your file content using a PUT request to that URL. The file will be processed in the background and indexed into your knowledge base.

```bash
curl -X PUT --data-binary @yourfile.pdf "$UPLOAD_URL"
```

You can pass an optional `id` to upsert. Calling this endpoint again with the same `id` overwrites the previous document once the new upload completes. Each call still returns a fresh `uploadUrl`.

For detailed documentation on the upload step, see the [Google Cloud Storage resumable uploads documentation](https://cloud.google.com/storage/docs/resumable-upload).


## OpenAPI

````yaml /api-reference/openapi.json post /documents/{data_source_id}/upload
openapi: 3.1.1
info:
  title: Realm API
  version: 0.0.1
  description: |2

      <p>
        Welcome to the Realm API documentation. With this API you can add, edit and delete documents from Realm, as well as integrate Realm into your applications.
      </p>

      <h2>Getting Started</h2>
      <ol>
        <li>First, you'll need to create an API token. You can create your own API token on the <a href="/settings">Settings page</a>, or ask your admin to create one for you on the <a href="/admin/api-access-tokens">Admin API page</a>.
        </li>
        <li>Include your API token in all requests using the Authorization header:
          <pre>Authorization: Bearer [your-api-token]</pre>
        </li>
      </ol>

      <h2>Rate Limits</h2>
      <p>
        This API implements rate limiting using a token bucket algorithm to ensure fair usage and system stability. When rate limits are exceeded, the API will return a 429 Too Many Requests status code.
      </p>
      <p>
        Each endpoint has its own rate limit configuration. If you exceed the rate limit, the request will be queued for up to 3 seconds before being rejected. We recommend implementing exponential backoff in your client applications when receiving 429 responses.
      </p>

      <h2>Pricing</h2>
      <p>
        The API does not have a separate pricing for now; it is included in the Realm subscription. We might change this in the future, but will notice you well in advance if we do.
      </p>

      <h2>Need Help?</h2>
      <p>
        If you encounter any issues or have questions, please contact our team in Slack or via email: <a href="mailto:team@withrealm.com">team@withrealm.com</a>
      </p>
servers:
  - url: https://app.withrealm.com/api/external/alpha
    description: Default multi-tenant environment.
  - url: https://{tenant}.withrealm.com/api/external/alpha
    description: Single-tenant deployment.
    variables:
      tenant:
        default: your-tenant
        description: Your organization's tenant subdomain.
security: []
tags:
  - name: Chats
    description: Endpoints for chat and message management
  - name: Documents
    description: >-
      Endpoints for document management and operations. These endpoints can be
      used with custom connectors - they will not work with pre-built
      connectors. To use these endpoints, you'll need to create a custom
      connector from the <a href='/admin/connect'>Connectors page</a>.
  - name: Connectors
    description: Endpoints for connector management and operations
    x-group: Data sources
  - name: Agents
    description: Endpoints for agent management and operations
paths:
  /documents/{data_source_id}/upload:
    post:
      tags:
        - Documents
      summary: Upload a file
      description: >-
        This endpoint initiates an upload session and returns an `uploadUrl` for
        the session. Upload your file content using PUT requests to the returned
        `uploadUrl`. The file will be processed in the background and indexed
        into your knowledge base once the upload is complete.


        ```

        curl -i -X PUT --data-binary @test.txt "$URL"

        ```

        The resumable uploads use Google Cloud Storage - for more detailed
        documentation on how to perform the upload step (once you have generated
        the upload URL) see the [Google Cloud Storage
        documentation](https://cloud.google.com/storage/docs/resumable-upload).


        Pass an optional `id` in the request body to upsert a previously
        uploaded document. A subsequent call with the same `id` overwrites the
        existing document once the new upload finishes processing. Each call
        still returns a fresh `uploadUrl`, so concurrent uploads to the same
        `id` do not clobber each other in storage (the last one to finish wins).


        This endpoint requires a Data Source ID. To get started:


        1. Go to the <a href='/admin/connect'>Connectors page</a>

        2. Create a new API Connector

        3. Copy the data source ID from the connector details page

        4. Use this ID in the {data_source_id} path parameter


        ### Rate Limits


        600 requests per minute.
      operationId: uploadDocumentFile
      parameters:
        - schema:
            type: string
            description: ID of the custom API data source.
          required: true
          description: ID of the custom API data source.
          in: path
          example: ds_kb_main
          name: data_source_id
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/DocumentUploadInput'
      responses:
        '200':
          description: Success
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/DocumentUploadOutput'
        '400':
          description: Bad request
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                  details:
                    type: string
                required:
                  - error
        '401':
          description: 'Unauthorized: missing or invalid API token'
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                required:
                  - error
        '403':
          description: >-
            Forbidden: the API token lacks the required scope, or external API
            access is not available on the organization's plan
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                required:
                  - error
        '429':
          description: >-
            Too many requests: rate limit exceeded. Retry after the number of
            seconds in the Retry-After response header.
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                required:
                  - error
        '500':
          description: Internal server error
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                required:
                  - error
      security:
        - bearerAuth: []
components:
  schemas:
    DocumentUploadInput:
      type: object
      properties:
        id:
          type: string
          pattern: ^[a-zA-Z0-9_-]+$
          description: >-
            Optional unique identifier for the document. We enforce uniqueness
            on our end. Calling this endpoint again with the same `id` will
            overwrite the previously uploaded document once the new upload
            finishes processing. If not provided, a UUID will be generated
            automatically and returned as `sourceId` in the response. Must be
            alphanumeric and can include underscores and hyphens.
        title:
          type: string
        meta:
          type: object
          additionalProperties: {}
        mimeType:
          type: string
        url:
          type: string
          format: uri
        createdAt:
          type: string
          format: date-time
          description: UTC timestamp in ISO 8601 format (e.g. '2024-03-20T10:00:00Z')
        updatedAt:
          type: string
          format: date-time
          description: UTC timestamp in ISO 8601 format (e.g. '2024-03-20T10:00:00Z')
        readAccess:
          type: array
          items:
            type: string
          minItems: 1
          description: >-
            Email addresses of the users that have read access to the document.
            If not provided, the document can be seen by anyone in Realm. Cannot
            be an empty array — omit the field instead.
        verified:
          type: boolean
          description: >-
            When true, marks the uploaded document as verified after processing.
            Include it on future uploads for the same source ID while the source
            system still treats it as authoritative; omitting it or sending
            false stops asserting source verification.
      required:
        - title
      example:
        id: doc_42
        title: handbook.pdf
        meta:
          category: guide
        mimeType: application/pdf
        url: https://docs.example.com/handbook.pdf
        createdAt: '2024-03-20T10:00:00Z'
        updatedAt: '2024-03-20T10:00:00Z'
        readAccess:
          - alice@example.com
        verified: true
    DocumentUploadOutput:
      type: object
      properties:
        uploadUrl:
          type: string
        sourceId:
          type: string
      required:
        - uploadUrl
        - sourceId
      example:
        uploadUrl: https://storage.googleapis.com/upload/resumable/xyz
        sourceId: doc_42
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      x-default: YOUR_API_TOKEN

````