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

# Create Upload

Upload an image or submit a link for community voting.

## Upload Types

| Type        | Description                       |
| ----------- | --------------------------------- |
| `image`     | Upload an image file              |
| `image_url` | Submit a URL to an image          |
| `link`      | Submit a link to external content |

## Image Upload

<CodeGroup>
  ```bash cURL theme={null}
  curl -X POST https://fucksornot.com/api/upload \
    -H "Cookie: auth-token=YOUR_JWT_TOKEN" \
    -F "upload_type=image" \
    -F "description=Check out this cool gadget" \
    -F "tags=gadget,tech" \
    -F "file=@/path/to/image.jpg"
  ```

  ```javascript JavaScript theme={null}
  const form = new FormData();
  form.append('upload_type', 'image');
  form.append('description', 'Check out this cool gadget');
  form.append('tags', 'gadget,tech');
  form.append('file', imageFile);

  const response = await fetch('https://fucksornot.com/api/upload', {
    method: 'POST',
    credentials: 'include', // sends the auth-token cookie
    body: form
  });
  ```

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

  with open('image.jpg', 'rb') as f:
      response = requests.post(
          'https://fucksornot.com/api/upload',
          cookies={'auth-token': 'YOUR_JWT_TOKEN'},
          files={'file': f},
          data={
              'upload_type': 'image',
              'description': 'Check out this cool gadget',
              'tags': 'gadget,tech'
          }
      )
  ```
</CodeGroup>

## Image URL Upload

The `image_url` upload type is only available on the cookie-authenticated `/api/upload` endpoint (not `/api/v1/upload`). FoN will download and process the image from the given URL.

```bash theme={null}
curl -X POST https://fucksornot.com/api/upload \
  -H "Cookie: auth-token=YOUR_JWT_TOKEN" \
  -F "upload_type=image_url" \
  -F "description=Found this online" \
  -F "image_url=https://example.com/image.jpg"
```

## Link Upload

```bash theme={null}
curl -X POST https://fucksornot.com/api/upload \
  -H "Cookie: auth-token=YOUR_JWT_TOKEN" \
  -F "upload_type=link" \
  -F "description=Great video" \
  -F "external_url=https://youtube.com/watch?v=..."
```

### Supported Platforms

Links from these platforms get rich embeds:

* Bluesky
* Instagram
* Threads
* YouTube
* Tumblr
* Spotify

## Parameters

| Parameter      | Type   | Required       | Description                                 |
| -------------- | ------ | -------------- | ------------------------------------------- |
| `upload_type`  | string | Yes            | `image`, `image_url`, or `link`             |
| `description`  | string | Yes            | Description (max 500 characters)            |
| `file`         | file   | For image      | Image file (JPEG, PNG, GIF, WebP, max 10MB) |
| `image_url`    | string | For image\_url | URL to image                                |
| `external_url` | string | For link       | URL to embed                                |
| `tags`         | string | No             | Comma-separated tags (max 10)               |
| `is_private`   | string | No             | `"true"` or `"false"`                       |

## Response

```json theme={null}
{
  "upload": {
    "id": "550e8400-e29b-41d4-a716-446655440000",
    "userId": "user-uuid",
    "filename": "abc123.webp",
    "originalName": "myimage.jpg",
    "description": "Check out this cool gadget",
    "uploadType": "image",
    "externalUrl": null,
    "isPrivate": false
  }
}
```

<Note>
  This is the immediate creation response and only includes a subset of fields. To get the full upload object (including `tags`, `username`, vote counts, and `stats`), fetch it afterwards with [`GET /api/upload/{id}`](/api-reference/uploads/get).
</Note>

## Duplicate Detection

If the image has already been uploaded:

```json theme={null}
{
  "duplicate": true,
  "existingUploadId": "existing-upload-uuid",
  "message": "This image has already been uploaded"
}
```

## API Token Upload

For programmatic access, use the `/api/v1/upload` endpoint with an API token:

```bash theme={null}
curl -X POST https://fucksornot.com/api/v1/upload \
  -H "Authorization: Bearer 7f3a9c2e1b6d4f8a0c5e7b9d2f4a6c8e1b3d5f7a9c0e2b4d6f8a1c3e5b7d9f0a" \
  -F "upload_type=image" \
  -F "description=Automated upload" \
  -F "file=@image.jpg"
```

<Note>
  `/api/v1/upload` only accepts `image` or `link` for `upload_type` — `image_url` is not supported on this endpoint and will return a `400 Invalid upload type` error. To submit an image by URL, use the cookie-authenticated `/api/upload` endpoint shown above.
</Note>

## Rate Limiting

Uploads are limited to **20 per hour** per user.
