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

# Upload File

> Upload files to a server using a signed URL

## Endpoint

```
POST /upload/file
```

## Authentication

This endpoint uses **JWT authentication** via a signed upload URL token, not Bearer token authentication.

The JWT token must be included in the query string as the `token` parameter.

## Query Parameters

<ParamField query="token" type="string" required>
  Signed JWT token authorizing the upload. Generated by the Panel.
</ParamField>

## JWT Payload

The JWT token must contain:

<ParamField body="server_uuid" type="string" required>
  The UUID of the server
</ParamField>

<ParamField body="unique_id" type="string">
  Optional unique identifier for one-time use enforcement
</ParamField>

## Request Body

Multipart form data with file uploads.

<ParamField body="files" type="file[]" required>
  One or more files to upload
</ParamField>

<ParamField body="directory" type="string" default="/">
  Target directory path (relative to server root)
</ParamField>

## Response

Returns `204 No Content` on success.

## Example Request

<CodeGroup>
  ```bash cURL theme={null}
  curl -X POST "https://wings.example.com/upload/file?token=SIGNED_JWT_TOKEN" \
    -F "files=@/path/to/local/file.txt" \
    -F "files=@/path/to/another/file.zip" \
    -F "directory=/uploads"
  ```

  ```javascript JavaScript theme={null}
  const formData = new FormData();
  formData.append('files', fileInput.files[0]);
  formData.append('directory', '/uploads');

  await fetch('https://wings.example.com/upload/file?token=SIGNED_JWT_TOKEN', {
    method: 'POST',
    body: formData
  });
  ```

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

  files = {
      'files': open('/path/to/file.txt', 'rb')
  }
  data = {
      'directory': '/uploads'
  }

  requests.post(
      'https://wings.example.com/upload/file',
      params={'token': 'SIGNED_JWT_TOKEN'},
      files=files,
      data=data
  )
  ```

  ```html HTML Form theme={null}
  <form action="https://wings.example.com/upload/file?token=SIGNED_JWT_TOKEN" 
        method="POST" 
        enctype="multipart/form-data">
    <input type="file" name="files" multiple>
    <input type="hidden" name="directory" value="/uploads">
    <button type="submit">Upload</button>
  </form>
  ```
</CodeGroup>

## Behavior

* Multiple files can be uploaded in a single request
* Files are written to the specified directory
* Parent directories are created automatically if they don't exist
* Existing files with the same name are overwritten
* Upload size is limited by the `upload_limit` configuration (default: 100 MB)
* JWT tokens can be marked as one-time use and will be invalidated after the first upload
* Ignored files (`.pteroignore`) cannot be uploaded

<Warning>
  The upload limit is configured in the Wings config.yml file under `api.upload_limit`. Large file uploads may time out based on network speed and server configuration.
</Warning>

## Rate Limiting

Uploads are subject to Wings' general rate limiting configuration. Very large or numerous uploads may be throttled.

## Error Responses

<AccordionGroup>
  <Accordion title="400 Bad Request">
    Invalid multipart form data or missing files
  </Accordion>

  <Accordion title="401 Unauthorized">
    Missing or invalid JWT token
  </Accordion>

  <Accordion title="403 Forbidden">
    File is on the ignore list or path traversal attempt
  </Accordion>

  <Accordion title="413 Payload Too Large">
    File exceeds upload\_limit configuration
  </Accordion>

  <Accordion title="500 Internal Server Error">
    Failed to save file (disk full, permission error, etc.)
  </Accordion>
</AccordionGroup>

## JWT Token Generation

Upload tokens are typically generated by the Pterodactyl Panel and passed to the client. The token should:

* Include the `server_uuid` claim
* Have a short expiration time (recommended: 5-15 minutes)
* Optionally include a `unique_id` for one-time use

## Source Reference

Implementation: `router/router_server_files.go` (postServerUploadFiles function)
