APIs and Controller - shleen/threadline GitHub Wiki
POST /clothing/create
Description
Create clothing item with the tags in the back end database and upload picture of clothing to R2 bucket. This clothing item will then be available in the wardrobe view.
Request Parameters
Parameter | Type | Description |
---|---|---|
username |
string |
current user attempting to upload clothing item |
type |
string |
clothing item type (For Example, top, bottom, or shoes?) |
subtype |
string |
clothing item subtype (For example, T-Shirt, Shorts, or Sneakers?) |
fit |
string |
clothing item fit |
layerable |
boolean |
Optional, If the clothing item can be added into a layered outfit, default is False |
precip |
string |
Optional, Is the clothing suitable for rainy or snowy weather? Default is null |
occasion |
string |
Occasion of clothing (For example, casual or formal?) |
winter |
boolean |
Is this piece of clothing suitable for winter? |
image |
File | PNG image file of the clothing item, should have its background removed via /image/process |
red |
int |
Red component of RGB value of clothing item's primary color (0-255) |
red_secondary |
int |
Red component of RGB value of clothing item's secondary color (0-255) |
green |
int |
Green component of RGB value of clothing item's primary color (0-255) |
green_secondary |
int |
Green component of RGB value of clothing item's secondary color (0-255) |
blue |
int |
Blue component of RGB value of clothing item's primary color (0-255) |
blue_secondary |
int |
Blue component of RGB value of clothing item's secondary color (0-255) |
tags |
{ [key: string]: string } |
Optional, Custom tags for clothing item in key-value pairs |
Response Codes
Code | Description |
---|---|
200 OK |
Success |
400 Bad Request |
Missing or invalid parameters |
Source Code
- API Endpoint Controller
- Image file Temporary Storage
- RGB to CIELAB Conversion Function
- User Retrieve or Create Function
GET /closet/get
Description
Returns all clothing items a user has stored in digital closet. Can optionally filter by type.
Request Parameters
Parameter | Type | Description |
---|---|---|
username |
string |
Current user attempting to get closet |
type |
string |
Type of clothing to filter by |
Response Codes
Code | Description |
---|---|
200 OK |
Success |
400 Bad Request |
Username not provided |
404 Not Found |
Username cannot be found |
JSON Response
Key | Type | Description |
---|---|---|
items |
List of JSON objects | List of clothing item matching the query |
Key | Type | Description |
---|---|---|
id |
int |
Global unique ID of clothing item |
type |
string |
Type of clothing item |
subtype |
string |
Subtype of clothing item |
img_filename |
string |
Filename of the image of the clothing item |
fit |
string |
Fit of clothing item |
layerable |
bool |
Is the clothing item allowed to appear in a layered outfit? |
precip |
string |
Precipitation of clothing item |
occasion |
string |
Occasion of clothing item |
weather |
string |
Weather of clothing item |
created_at |
string |
Datetime string the clothing item was created at |
tags |
List of JSON Objects | Custom tags added by the user |
colors_primary |
List of ints | RGB value of primary color |
colors_secondary |
List of ints | RGB value of secondary color |
Key | Type | Description |
---|---|---|
label |
string |
Label of the tag |
value |
string |
value of the tag |
Example Response
$ curl https://<SERVER_DOMAIN>/closet/get?username=bob&type=TOP
{
"items": [
{
"id": 103,
"type": "TOP",
"subtype": "T-SHIRT",
"img_filename": "bob_1744329365307.png",
"fit": "TIGHT",
"layerable": false,
"precip": "RAIN",
"occasion": "ACTIVE",
"weather": "WINTER",
"created_at": "2025-04-10T23:56:05.584Z",
"tags": [
{
"label": "brand",
"value": "brand_2"
},
{
"label": "random",
"value": "tag_486"
}
],
"colors_primary": [
255,
63,
0
],
"colors_secondary": [
0,
255,
0
]
}, ...
}
Source Code
GET /recommendation/get
Description Returns a list of recommended outfits for a user based on their location's weather conditions.
Request Parameters
Parameter | Type | Description |
---|---|---|
username |
string |
Current user requesting outfit recommendations |
lat |
float |
Latitude of the user's location |
lon |
float |
Longitude of the user's location |
Response Codes
Code | Description |
---|---|
200 OK |
Success |
400 Bad Request |
Missing or invalid parameters |
JSON Response
Key | Type | Description |
---|---|---|
outfits |
List of JSON objects | List of recommended outfits based on weather and user preferences |
Example Response
{
"outfits": [
{
"clothes": [
{
"id": 0,
"img": "alice_1877658930.png",
"type": "TOP"
},
{
"id": 1,
"img": "alice_1291012510.png",
"type": "BOTTOM"
},
{
"id": 2,
"img": "alice_1693409716.png",
"type": "SHOES"
},
{
"id": 3,
"img": "alice_1693409716.png",
"type": "TOP"
},
{
"id": 4,
"img": "alice_1693409716.png",
"type": "OUTERWEAR"
}
]
},
{
"clothes": [
{
"id": 5,
"img": "alice_1188692249.png",
"type": "TOP"
},
{
"id": 6,
"img": "alice_1665866575.png",
"type": "BOTTOM"
},
{
"id": 7,
"img": "alice_1629574246.png",
"type": "SHOES"
}
]
}
]
}
Source Code
- API Endpoint Controller
- Weather Retrieval Function
- Reranking Section of Query
- Ranking SQL Query
- Query Execution Function
- Ranking Python Data Manipulation
- Outfit Recommendation Logic
GET /outfits/get
Description
Returns up to 15 outfits that the user has most recently worn. If the user is using the app daily, this will translate to what they wore in the past two weeks. However, if the user's usage is more sparse, we will still show them outfits regardless of wear times.
Request Parameters
Parameter | Type | Description |
---|---|---|
username |
string |
current user attempting to view outfits |
Response Codes
Code | Description |
---|---|
200 OK |
Success |
400 Bad Request |
Username not provided |
JSON Response
Key | Type | Description |
---|---|---|
outfits |
List of JSON Objects | Up to 15 most recently worn outfits |
Key | Type | Description |
---|---|---|
outfit_id |
Integer |
Unique identifier of the outfit in the database |
timestamp |
Datetime string | Date when the outfit was worn |
clothes |
List of JSON objects | List of garments in the outfit |
Key | Type | Description |
---|---|---|
clothing_id |
Integer |
Unique identifier of the garment in the database |
img |
string |
File name associated with the garment in Cloudflare R2 |
Example Response
{
"outfits": [
{
"outfit_id": 7,
"timestamp": "2025-03-23T20:35:17.041Z",
"clothes": [
{
"clothing_id": 1,
"img": "alice_1743875203889.png"
},
{
"clothing_id": 4,
"img": "alice_1743875210746.png"
},
{
"clothing_id": 4,
"img": "alice_1743875210746.png"
}
]
},
{
"outfit_id": 5,
"timestamp": "2025-01-25T20:35:17.041Z",
"clothes": [
{
"clothing_id": 3,
"img": "alice_1743875207169.png"
}
]
},
{
"outfit_id": 4,
"timestamp": "2024-12-04T20:35:17.041Z",
"clothes": [
{
"clothing_id": 3,
"img": "alice_1743875207169.png"
}
]
},
{
"outfit_id": 1,
"timestamp": "2024-03-01T20:35:17.041Z",
"clothes": [
{
"clothing_id": 2,
"img": "alice_1743875204437.png"
}
]
}
]
}
Source Code
POST /outfit/post
Description Allows users to log what they are wearing for the day. They can optionally provide a picture of themselves wearing that outfit to share that with the community.
Request Parameters
Parameter | Type | Description |
---|---|---|
username |
string |
current user attempting to log outfit |
clothing_ids |
string[] |
list of ids that consists of the outfit |
image |
File | Image file to be shared with the community |
Response Codes
Code | Description |
---|---|
200 OK |
Success |
400 Bad Request |
Missing/Invalid Parameter or Cloudflare Upload error |
Source Code
GET /utilization/get
Description
Returns garment wearing statistics to the user. This includes the most reworn garments for each type of clothing, the total percent utilization, and utilization of each type of their clothing all computed over the past month from present date.
Request Parameters
Parameter | Type | Description |
---|---|---|
username |
string |
current user attempting to view analytics |
Response Codes
Code | Description |
---|---|
200 OK |
Success |
400 Bad Request |
Username not provided |
JSON Response
Key | Type | Description |
---|---|---|
utilization |
JSON Object | Encapsulates analytics data |
Key | Type | Description |
---|---|---|
TOTAL |
float |
Total utilization percentage for the user's wardrobe |
utilization |
List of JSON Objects | Encapsulates the type of clothing and its percent utilization |
rewears |
List of JSON Objects | Garments that have been reworn the most |
Key | Type | Description |
---|---|---|
util_type |
string |
The type of clothing for which the percentage is computed |
percentage |
float |
Percent utilization for the above type |
Key | Type | Description |
---|---|---|
id |
Integer |
Unique id for garment from the database |
type |
string |
Type of clothing of the reworn garment |
img_filename |
string |
File name associated with the garment stored in Cloudflare R2 |
wears |
Integer |
Number of times the garment was worn |
Example Response
{
"utilization": {
"TOTAL": 0.25,
"utilization": [
{
"util_type": "TOP",
"percent": 0.25
}
]
},
"rewears": [
{
"id": 4,
"type": "TOP",
"img_filename": "alice_1743875210746.png",
"wears": 2
}
]
}
Source Code
- SQL Query (Utilization)
- SQL Query (Rewears)
- Query Execution Function
- Python Data Manipulation (Utilization)
- Python Data Manipulation (Rewears)
- API Controller
POST /image/process
Description Takes a PNG image of a clothing item, returns its primary and secondary colors in RGB as well as the image with its background removed in the form of a base64 encoded string
Request Parameters
Parameter | Type | Description |
---|---|---|
username |
string |
current user attempting to process image |
image |
File | PNG image file of clothing item |
Response Codes
Code | Description |
---|---|
200 OK |
Success |
400 Bad Request |
File format is not PNG |
JSON Response
Key | Type | Description |
---|---|---|
colors |
int[][] |
Primary and Secondary colors of the clothing item in RGB values |
image_base64 |
string |
Image with background removed encoded in base64 |
Example Response
{
"colors": "[90, 90, 70], [202, 202, 200](/shleen/threadline/wiki/90,-90,-70],-[202,-202,-200)",
"image_base64": <IMAGE_DATA_BASE64_ENCODED>
}
Source Code
- API Endpoint Controller
- Image File Temporary Storage Function
- Image Background Removal Function
- Color Palette Extraction Function
- Image Compression Function
GET /categories/get
Description
Returns all tags to be used by the frontend in order to avoid hardcoding. Fields include:
- Clothing types
- Occasions
- Fits
- Precipitation
- Clothing
- Subtypes for each given clothing type
- Weather/seasons
Request Parameters None. Tags are global across all users.
Response Codes
Code | Description |
---|---|
200 OK |
Success |
JSON Response
Key | Type | Description |
---|---|---|
type |
List of strings | List of types of clothing supported that can be tagged |
occasion |
List of strings | List of supported occasions that can be tagged |
fit |
List of strings | List of supported fits that can be tagged |
precip |
List of strings | List of supported precipitations that can be tagged |
`subtype' | List of JSON Objects | Data encapsulating subtypes which may be used for tagging |
weather |
List of strings | List of supported seasons/weather conditions that may be used for tagging |
Key | Type | Description |
---|---|---|
type |
string |
The type of clothing associated with the forthcoming subtypes |
type |
List of strings | List of supported subtypes that belong to the above clothing type for tagging |
Example Response
{
"type": [
"TOP",
"BOTTOM",
"OUTERWEAR",
"DRESS",
"SHOES"
],
"occasion": [
"ACTIVE",
"CASUAL",
"FORMAL"
],
"fit": [
"LOOSE",
"FITTED",
"TIGHT"
],
"precip": [
"RAIN",
"SNOW"
],
"subtype": [
{
"type": "TOP",
"subtypes": [
"ACTIVE",
"T_SHIRT",
"POLO",
"BUTTON_DOWN",
"HOODIE",
"SWEATER"
]
},
{
"type": "BOTTOM",
"subtypes": [
"ACTIVE",
"JEANS",
"PANTS",
"SHORTS",
"SKIRT"
]
},
{
"type": "DRESS",
"subtypes": [
"MINI",
"MIDI",
"MAXI"
]
},
{
"type": "OUTERWEAR",
"subtypes": [
"JACKET",
"COAT"
]
},
{
"type": "SHOES",
"subtypes": [
"ACTIVE",
"SNEAKERS",
"BOOTS",
"SANDALS_SLIDES"
]
}
],
"weather": [
"WINTER",
"SUMMER"
]
}
Source Code
- API Endpoint Controller
- Gathering Categories
- Database Fields For Categories
- Globals Extracting Database Fields
GET /declutter/get
Description
Returns a list of JSON objects recommending items in the wardrobe that should be removed. Recommendation returns items that meet the following criteria following criteria:
- Garment was never worn or most recent wear occurred more than a month ago from present date
- Garment was added to the wardrobe more than a month ago from present date. This is to prevent new wardrobe items from being immediately suggested to remove.
Items are ordered in ascending order by the number of times they have been worn, such that those worn the least are shown first.
Request Parameters
Parameter | Type | Description |
---|---|---|
username |
string |
current user attempting to declutter |
Response Codes
Code | Description |
---|---|
200 OK |
Success |
400 Bad Request |
Username not provided |
JSON Response
Key | Type | Description |
---|---|---|
declutter |
List of JSON Objects | List of items recommended for the user to remove |
Key | Type | Description |
---|---|---|
id |
Integer |
Unique database id for garment |
img_filename |
string |
Name of image file associated with garment stored in Cloudflare R2 |
recent |
Nullable date time string | Date of garment's most recent wear. Can be null if never worn |
wear_counts |
Integer |
Non-negative integer counting the number of times a garment has been worn |
Example Response
{
"declutter": [
{
"id": 5,
"img_filename": "alice_1743875212015.png",
"recent": null,
"wear_counts": 0
},
{
"id": 6,
"img_filename": "alice_1743875207716.png",
"recent": null,
"wear_counts": 0
},
{
"id": 7,
"img_filename": "alice_1743875208014.png",
"recent": null,
"wear_counts": 0
},
{
"id": 3,
"img_filename": "alice_1743875207169.png",
"recent": "2025-01-25T20:35:17.041Z",
"wear_counts": 2
}
]
}
Source Code
POST /declutter/post
Description Receives a list of clothing ids to remove from the database. Deletion involves marking a garment as deleted instead of removing the record from the table.
Request Parameters None
Response Codes
Code | Description |
---|---|
200 OK |
Success |
400 Bad Request |
No ids provided or invalid ids provided |
Request JSON
Key | Type | Description |
---|---|---|
ids | List of integers | Ids of clothing to mark as deleted |
Example Request
{
"ids": [1, 2, 3]
}
Source Code
GET /feed/get
Description
Returns outfits from all users that have been logged with an outfit picture, in reverse chronological order. Cursor-based pagination is implemented.
Request Parameters
Parameter | Type | Description |
---|---|---|
username |
string |
Current user's username. |
cursor |
string |
Optional. Cursor representing where the endpoint will begin returning outfits from. |
page_size |
int |
Optional. Maximum number of outfits that should be returned. Defaults to 10. |
Response Codes
Code | Description |
---|---|
200 OK |
Success |
400 Bad Request |
Username not provided or bad cursor format provided |
404 Not Found |
Username provided does not refer to an existing user |
JSON Response
Key | Type | Description |
---|---|---|
outfits |
Outfit[] | List of outfits items, sorted in reverse chronological order, with images. |
next_cursor |
string | null |
If not null, there are more feed items that can be retrieved. The value of next_cursor can be passed into the next call to this endpoint to begin retrieving the next page. |
Example Response
{
"outfits": [
{
"id": 16,
"img_filename": "outfit/bob_1745089026425.jpeg",
"date_worn": "2025-04-19T18:57:06.425184+00:00",
"username": "bob",
"clothing_items": [
{
"id": 12,
"type": "SHOES",
"subtype": "SNEAKERS",
"img_filename": "bob_1740687133645.png",
"color_lstar": 76.68889540018786,
"color_astar": 39.75402632707642,
"color_bstar": 93.68991375511732,
"fit": "LOOSE",
"layerable": true,
"precip": null,
"occasion": "FORMAL",
"weather": "SUMMER",
"created_at": "2025-02-27T20:12:14.153457+00:00",
"tags": [
{
"label": "brand",
"value": "brand_1"
}
]
}
],
"is_liked": true
}
],
"next_cursor": "2025-04-19T18:56:48.498237+00:00"
}
Source Code
3rd Party Weather API
Description Threadline uses the OpenWeatherMap API for weather insights.
This service provides real-time weather data used to filter and recommend appropriate outfits based on current conditions. The server calls the https://api.openweathermap.org/data/2.5/weather
endpoint supplying an API key, latitude, longitude, and unit system as query parameters. The backend will then consume the JSON response and interpret it to classify weather conditions. In particular, temperatures are given in Fahrenheit which are then compared against ranges that map to different seasons like Summer or Winter. As for precipitation, the API response contains an id value for this condition. If the is in the range [200, 599], rain is predicted, and if it is in [600, 699] snow is predicted. The season and precipitation classifications are then used by the ranking stage of the algorithm to pull items from the database that are only appropriate for this weather.