---
title: Use a custom style
description: Upload your own style image and use it on POST /predict.
url: https://artfloe-docs.thally.app/guides/use-a-custom-style
---

# Use a custom style

Upload your own style image and use it on POST /predict.

A custom style is a reference image you upload. It is stored in Supabase Storage bucket `style-uploads` and scoped to your account. Catalog styles stay on the Modal volume.

Default cap: 100 custom styles per account (`MAX_CUSTOM_STYLES`). Hitting the cap returns `custom_style_limit_exceeded`.

## In the studio

1. Sign in at [artfloe.fun](https://artfloe.fun).
2. Under **Choose a Style**, open the custom-style upload tile (it triggers the hidden file input).
3. Pick a JPEG, PNG, BMP, or WebP under 8 MB.
4. Wait until the new thumbnail appears in the slider, then select it.
5. Click **Transform**.

The studio sends `style_img_name` as `custom_<uuid>.<ext>`.

Deleting a custom style asks for confirmation: **Are you sure you want to delete this custom style? This can't be undone.**

## Via HTTP

### Upload

```bash
curl -sS https://artfloe.fun/upload_style \
  -H 'Authorization: Bearer eyJhbGciOiJFUzI1NiIsInR5cCI6IkpXVCJ9...' \
  -H 'Sec-Fetch-Site: none' \
  -F 'image=@my-painting.jpg'
```

Expected response:

```json
{
  "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "filename": "custom_3fa85f64-5717-4562-b3fc-2c963f66afa6.jpg",
  "display_name": "my painting",
  "url": "/custom_styles/3fa85f64-5717-4562-b3fc-2c963f66afa6/image"
}
```

Use `filename` as `style_img_name` on `/predict`. NudeNet runs before Storage write; a flagged image returns `422` `content_rejected`.

### List

```bash
curl -sS https://artfloe.fun/custom_styles \
  -H 'Authorization: Bearer eyJhbGciOiJFUzI1NiIsInR5cCI6IkpXVCJ9...'
```

Expected response:

```json
{
  "styles": [
    {
      "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
      "filename": "custom_3fa85f64-5717-4562-b3fc-2c963f66afa6.jpg",
      "display_name": "my painting",
      "url": "/custom_styles/3fa85f64-5717-4562-b3fc-2c963f66afa6/image",
      "created_at": "2026-09-13T16:01:00+00:00"
    }
  ]
}
```

You only see your own rows. Image bytes are at `GET /custom_styles/<id>/image` with the same Bearer token.

### Generate with it

```bash
curl -sS -N https://artfloe.fun/predict \
  -H 'Authorization: Bearer eyJhbGciOiJFUzI1NiIsInR5cCI6IkpXVCJ9...' \
  -H 'Content-Type: application/json' \
  -H 'Sec-Fetch-Site: none' \
  -d '{
    "content_img_name": "content_a1b2c3d4_photo.jpg",
    "style_img_name": "custom_3fa85f64-5717-4562-b3fc-2c963f66afa6.jpg"
  }'
```

Flask downloads the file onto the GPU volume before `run_nst_gpu`. A style you do not own returns `404` `Custom style not found or access denied` and cancels the quota reservation.

### Delete

```bash
curl -sS -X DELETE https://artfloe.fun/custom_styles/3fa85f64-5717-4562-b3fc-2c963f66afa6 \
  -H 'Authorization: Bearer eyJhbGciOiJFUzI1NiIsInR5cCI6IkpXVCJ9...' \
  -H 'Sec-Fetch-Site: none'
```

Expected response:

```json
{"ok": true}
```

Unknown or foreign IDs return `404` `not_found`.

Legacy public URLs under `/data/temp-styles/` are disabled.