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

# Generate File Upload URL

> Generate a presigned URL for uploading files to be used with the assistant

Generates a presigned URL that can be used to upload files directly to Wordsmith's storage. This is the first step when you want to include file attachments with your assistant questions.

## Authentication

This endpoint requires a valid API key in the Authorization header.

## Request Body

<ParamField body="file_name" type="string" required>
  The name of the file to be uploaded, including the file extension
</ParamField>

<ParamField body="content_type" type="string" required>
  The MIME type of the file (e.g., "application/pdf", "text/plain",
  "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
  "image/png", "audio/mp3")
</ParamField>

## Supported File Types

Wordsmith supports a wide variety of file formats including:

* **Documents**: PDF, DOC, DOCX, TXT, MD, HTML
* **Spreadsheets**: XLS, XLSX, CSV, TSV
* **Presentations**: PPT, PPTX
* **Images**: PNG, JPEG, WebP, TIFF
* **Audio**: MP3, MP4, M4A, MPEG, WAV, WebM
* **Archives**: ZIP

<CodeGroup>
  ```bash cURL theme={null}
  curl -X POST "https://api.wordsmith.ai/api/v1/files/upload-url" \
    -H "Authorization: Bearer sk-ws-api1-your_api_key_here" \
    -H "Content-Type: application/json" \
    -d '{
      "file_name": "contract.pdf",
      "content_type": "application/pdf"
    }'
  ```

  ```javascript JavaScript theme={null}
  const response = await fetch(
    "https://api.wordsmith.ai/api/v1/files/upload-url",
    {
      method: "POST",
      headers: {
        Authorization: "Bearer sk-ws-api1-your_api_key_here",
        "Content-Type": "application/json",
      },
      body: JSON.stringify({
        file_name: "contract.pdf",
        content_type: "application/pdf",
      }),
    }
  );

  const uploadInfo = await response.json();
  ```

  ```python Python theme={null}
  import requests

  headers = {
      "Authorization": "Bearer sk-ws-api1-your_api_key_here",
      "Content-Type": "application/json"
  }

  data = {
      "file_name": "contract.pdf",
      "content_type": "application/pdf"
  }

  response = requests.post(
      "https://api.wordsmith.ai/api/v1/files/upload-url",
      headers=headers,
      json=data
  )
  upload_info = response.json()
  ```
</CodeGroup>

## Response

<ResponseField name="upload_url" type="string">
  The presigned URL where you can upload your file using a PUT request.
</ResponseField>

<ResponseField name="job_id" type="string">
  The unique identifier for this upload job. Use this as the `upload_job_id` when creating assistant
  questions with file attachments.
</ResponseField>

<ResponseField name="content_type" type="string">
  The MIME type that was specified in the request.
</ResponseField>

<ResponseExample>
  ```json Response theme={null}
  {
    "upload_url": "https://s3.amazonaws.com/wordsmith-uploads/signed-url-here",
    "job_id": "123e4567-e89b-12d3-a456-426614174000",
    "content_type": "application/pdf"
  }
  ```
</ResponseExample>

## Complete Upload Flow

After receiving the upload URL, you need to upload your file:

<CodeGroup>
  ```bash cURL theme={null}
  # Step 1: Get upload URL (shown above)
  # Step 2: Upload the file
  curl -X PUT "https://s3.amazonaws.com/wordsmith-uploads/signed-url-here" \
    -H "Content-Type: application/pdf" \
    --data-binary @contract.pdf

  # Step 3: Use upload_job_id in your assistant question
  curl -X POST "https://api.wordsmith.ai/api/v1/assistants/default/questions" \
    -H "Authorization: Bearer sk-ws-api1-your_api_key_here" \
    -H "Content-Type: application/json" \
    -d '{
      "question": "Please review this contract",
      "attachments": [
        {
          "upload_job_id": "123e4567-e89b-12d3-a456-426614174000"
        }
      ]
    }'
  ```

  ```javascript JavaScript theme={null}
  // Step 1: Get upload URL
  const uploadResponse = await fetch(
    "https://api.wordsmith.ai/api/v1/files/upload-url",
    {
      method: "POST",
      headers: {
        Authorization: "Bearer sk-ws-api1-your_api_key_here",
        "Content-Type": "application/json",
      },
      body: JSON.stringify({
        file_name: "contract.pdf",
        content_type: "application/pdf",
      }),
    }
  );

  const { upload_url, job_id } = await uploadResponse.json();

  // Step 2: Upload the file
  const fileUploadResponse = await fetch(upload_url, {
    method: "PUT",
    headers: {
      "Content-Type": "application/pdf",
    },
    body: fileBlob,
  });

  // Step 3: Use in assistant question
  const questionResponse = await fetch(
    "https://api.wordsmith.ai/api/v1/assistants/default/questions",
    {
      method: "POST",
      headers: {
        Authorization: "Bearer sk-ws-api1-your_api_key_here",
        "Content-Type": "application/json",
      },
      body: JSON.stringify({
        question: "Please review this contract",
        attachments: [{ upload_job_id: job_id }],
      }),
    }
  );
  ```
</CodeGroup>

## Error Responses

See the [Errors](/errors) page for the full error format reference.

<ResponseExample>
  ```json 400 Bad Request - Invalid Body theme={null}
  {
    "error_code": "invalid_request_body",
    "ws_api_error_code": "invalid_request_body",
    "message": "Request body is invalid. Ensure it is valid JSON with 'file_name' and 'content_type' fields."
  }
  ```

  ```json 400 Bad Request - Unsupported File Type theme={null}
  {
    "error_code": "unsupported_file_type",
    "ws_api_error_code": "unsupported_file_type",
    "message": "The specified content type is not supported. See documentation for supported file types."
  }
  ```

  ```json 401 Unauthorized theme={null}
  {
    "error_code": "unauthorized",
    "ws_api_error_code": "unauthorized",
    "message": "Invalid API key"
  }
  ```
</ResponseExample>

## File Size Limits

* Maximum file size: 50 MB per file
* Maximum total attachments per question: 10 files
* Files are automatically deleted after 30 days for security

## Notes

* Upload URLs expire after 1 hour
* Files must be uploaded using a PUT request with the exact content type specified
* The `job_id` from the response should be passed as `upload_job_id` when creating assistant questions
