{"openapi":"3.1.0","info":{"title":"PlantIdentify API","description":"PlantIdentify backend for plant.hurated.com (port 34000 → 8080)","version":"0.1.0"},"paths":{"/health":{"get":{"summary":"Health","operationId":"health_health_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/health":{"get":{"summary":"Health","operationId":"health_api_health_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/queue/health":{"get":{"summary":"Queue Health","operationId":"queue_health_api_queue_health_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/v1/auth/anonymous":{"post":{"summary":"Auth Anonymous","operationId":"auth_anonymous_v1_auth_anonymous_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AnonymousRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/auth/refresh":{"post":{"summary":"Auth Refresh","operationId":"auth_refresh_v1_auth_refresh_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RefreshRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/auth/apple":{"post":{"summary":"Auth Apple","operationId":"auth_apple_v1_auth_apple_post","requestBody":{"content":{"application/json":{"schema":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Body"}}}},"responses":{"501":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/me":{"get":{"summary":"Me","operationId":"me_v1_me_get","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"type":"string","title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"summary":"Delete User Data","operationId":"delete_user_data_v1_me_delete","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"type":"string","title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/stats":{"get":{"summary":"Stats","operationId":"stats_v1_stats_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/v1/plants":{"get":{"summary":"List Plants","operationId":"list_plants_v1_plants_get","parameters":[{"name":"query","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Search by name/latin","title":"Query"},"description":"Search by name/latin"},{"name":"q","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Alias for query","title":"Q"},"description":"Alias for query"},{"name":"category","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Category"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"default":20,"title":"Limit"}},{"name":"offset","in":"query","required":false,"schema":{"type":"integer","minimum":0,"default":0,"title":"Offset"}},{"name":"ids","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Comma-separated plant ids (max 100), in this order","title":"Ids"},"description":"Comma-separated plant ids (max 100), in this order"},{"name":"full","in":"query","required":false,"schema":{"type":"boolean","description":"Include description, knowledge and the care profile","default":false,"title":"Full"},"description":"Include description, knowledge and the care profile"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/plants/trending":{"get":{"summary":"Trending Plants","description":"Plants people actually scan: most scan photos in the last 60 days\nfirst, then all time, then the newest plants. Only plants with a photo\nand a care profile; one per genus so the row isn't six maples.","operationId":"trending_plants_v1_plants_trending_get","parameters":[{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":50,"minimum":1,"default":12,"title":"Limit"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/plants/{plant_id}":{"get":{"summary":"Get Plant","operationId":"get_plant_v1_plants__plant_id__get","parameters":[{"name":"plant_id","in":"path","required":true,"schema":{"type":"string","title":"Plant Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/catalog/categories":{"get":{"summary":"Catalog Categories","operationId":"catalog_categories_v1_catalog_categories_get","parameters":[{"name":"per_category","in":"query","required":false,"schema":{"type":"integer","maximum":30,"minimum":0,"default":8,"title":"Per Category"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/search":{"get":{"summary":"Search","operationId":"search_v1_search_get","parameters":[{"name":"q","in":"query","required":true,"schema":{"type":"string","description":"Search query","title":"Q"},"description":"Search query"},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"default":20,"title":"Limit"}},{"name":"offset","in":"query","required":false,"schema":{"type":"integer","minimum":0,"default":0,"title":"Offset"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/geocode":{"get":{"summary":"Geocode","operationId":"geocode_v1_geocode_get","parameters":[{"name":"query","in":"query","required":true,"schema":{"type":"string","description":"City search, e.g. Malag","title":"Query"},"description":"City search, e.g. Malag"},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":10,"minimum":1,"default":5,"title":"Limit"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/cities/popular":{"get":{"summary":"Cities Popular","operationId":"cities_popular_v1_cities_popular_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/v1/geocode/reverse":{"get":{"summary":"Reverse","operationId":"reverse_v1_geocode_reverse_get","parameters":[{"name":"lat","in":"query","required":true,"schema":{"type":"number","title":"Lat"}},{"name":"lon","in":"query","required":true,"schema":{"type":"number","title":"Lon"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/location/reverse":{"get":{"summary":"Reverse","operationId":"reverse_v1_location_reverse_get","parameters":[{"name":"lat","in":"query","required":true,"schema":{"type":"number","title":"Lat"}},{"name":"lon","in":"query","required":true,"schema":{"type":"number","title":"Lon"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/location/by-ip":{"get":{"summary":"By Ip","operationId":"by_ip_v1_location_by_ip_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/v1/user/location":{"get":{"summary":"Get User Location","operationId":"get_user_location_v1_user_location_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}},"post":{"summary":"Set User Location","operationId":"set_user_location_v1_user_location_post","requestBody":{"content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Body"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/weather/batch":{"get":{"summary":"Weather Batch","description":"One upstream Open-Meteo call for many locations (it accepts arrays),\ncached 10 min on the server — N apps asking for the same cities cost 1 call.\nReturns {\"items\": [{\"lat\",\"lon\",\"temperature\",\"condition\",\"icon\"}]} in request order.","operationId":"weather_batch_v1_weather_batch_get","parameters":[{"name":"locs","in":"query","required":true,"schema":{"type":"string","description":"Pipe-separated lat,lon pairs, e.g. '36.7,-4.4|48.8,2.3' (max 20)","title":"Locs"},"description":"Pipe-separated lat,lon pairs, e.g. '36.7,-4.4|48.8,2.3' (max 20)"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/weather":{"get":{"summary":"Weather","operationId":"weather_v1_weather_get","parameters":[{"name":"city","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"City"}},{"name":"country","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Country"}},{"name":"lat","in":"query","required":false,"schema":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Lat"}},{"name":"lon","in":"query","required":false,"schema":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Lon"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/weather/forecast":{"get":{"summary":"Weather Forecast","operationId":"weather_forecast_v1_weather_forecast_get","parameters":[{"name":"lat","in":"query","required":true,"schema":{"type":"number","title":"Lat"}},{"name":"lon","in":"query","required":true,"schema":{"type":"number","title":"Lon"}},{"name":"days","in":"query","required":false,"schema":{"type":"integer","maximum":16,"minimum":1,"default":7,"title":"Days"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/identify":{"post":{"summary":"Identify","operationId":"identify_v1_identify_post","requestBody":{"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/Body_identify_v1_identify_post"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/diagnose":{"post":{"summary":"Diagnose","operationId":"diagnose_v1_diagnose_post","requestBody":{"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/Body_diagnose_v1_diagnose_post"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/leaf-check":{"post":{"summary":"Leaf Check","description":"Scores the leaf-check answers by the questions `/v1/content` serves\n(`leaf_check`): 100 minus the penalties of the chosen options; advice for\nevery option with a complaint. An answer that isn't one of the served\noptions is rejected (422), never counted as healthy.","operationId":"leaf_check_v1_leaf_check_post","requestBody":{"content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Body"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/care/check":{"post":{"summary":"Care Check","operationId":"care_check_v1_care_check_post","requestBody":{"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/Body_care_check_v1_care_check_post"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/articles":{"get":{"summary":"List Articles","operationId":"list_articles_v1_articles_get","parameters":[{"name":"tags","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Comma-separated tags (all must match): care,science,light","title":"Tags"},"description":"Comma-separated tags (all must match): care,science,light"},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"default":20,"title":"Limit"}},{"name":"offset","in":"query","required":false,"schema":{"type":"integer","minimum":0,"default":0,"title":"Offset"}},{"name":"q","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Search in title and text","title":"Q"},"description":"Search in title and text"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/articles/{article_id}":{"get":{"summary":"Get Article","operationId":"get_article_v1_articles__article_id__get","parameters":[{"name":"article_id","in":"path","required":true,"schema":{"type":"string","title":"Article Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/library/lists":{"get":{"summary":"Library Lists","operationId":"library_lists_v1_library_lists_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/v1/library/lists/{list_id}":{"get":{"summary":"Library List Detail","operationId":"library_list_detail_v1_library_lists__list_id__get","parameters":[{"name":"list_id","in":"path","required":true,"schema":{"type":"string","title":"List Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/library/lists/{list_id}/plants":{"get":{"summary":"Library List Plants","operationId":"library_list_plants_v1_library_lists__list_id__plants_get","parameters":[{"name":"list_id","in":"path","required":true,"schema":{"type":"string","title":"List Id"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"default":20,"title":"Limit"}},{"name":"offset","in":"query","required":false,"schema":{"type":"integer","minimum":0,"default":0,"title":"Offset"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/explore":{"get":{"summary":"Explore","description":"Plants matching ALL given filters, using only known values: a plant\nwhose light/soil/pH/... is unknown never matches that filter.\n\nWhen nothing matches and more than one filter is set, `relax` lists the\nfilters whose removal alone would bring plants back, with how many —\ne.g. full sun + chalk + acid + herbs + annual + pet-friendly is 0, but\nwithout pet-friendly it is 2 (both candidates are toxic to pets).","operationId":"explore_v1_explore_get","parameters":[{"name":"light","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"comma list: full sun, part sun, part shade, full shade, bright indirect, low light","title":"Light"},"description":"comma list: full sun, part sun, part shade, full shade, bright indirect, low light"},{"name":"soil","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"comma list of soil types (loam, sand, clay, chalk, ...)","title":"Soil"},"description":"comma list of soil types (loam, sand, clay, chalk, ...)"},{"name":"ph","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"acid | neutral | alkaline","title":"Ph"},"description":"acid | neutral | alkaline"},{"name":"type","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"category, e.g. Trees","title":"Type"},"description":"category, e.g. Trees"},{"name":"life","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"annual | biennial | perennial","title":"Life"},"description":"annual | biennial | perennial"},{"name":"safety","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"pet-safe | child-safe | toxic-humans | toxic-pets","title":"Safety"},"description":"pet-safe | child-safe | toxic-humans | toxic-pets"},{"name":"indoor","in":"query","required":false,"schema":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Indoor"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"default":20,"title":"Limit"}},{"name":"offset","in":"query","required":false,"schema":{"type":"integer","minimum":0,"default":0,"title":"Offset"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/filters/options":{"get":{"summary":"Filter Options","description":"Filter values that exist in the data, with how many listed plants have each.","operationId":"filter_options_v1_filters_options_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/v1/chats":{"get":{"summary":"List Chats","operationId":"list_chats_v1_chats_get","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"type":"string","title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"summary":"Create Chat","operationId":"create_chat_v1_chats_post","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"type":"string","title":"Authorization"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Body"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/chats/{chat_id}":{"get":{"summary":"Get Chat","operationId":"get_chat_v1_chats__chat_id__get","parameters":[{"name":"chat_id","in":"path","required":true,"schema":{"type":"string","title":"Chat Id"}},{"name":"authorization","in":"header","required":false,"schema":{"type":"string","title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"patch":{"summary":"Update Chat","operationId":"update_chat_v1_chats__chat_id__patch","parameters":[{"name":"chat_id","in":"path","required":true,"schema":{"type":"string","title":"Chat Id"}},{"name":"authorization","in":"header","required":false,"schema":{"type":"string","title":"Authorization"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Body"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"summary":"Delete Chat","operationId":"delete_chat_v1_chats__chat_id__delete","parameters":[{"name":"chat_id","in":"path","required":true,"schema":{"type":"string","title":"Chat Id"}},{"name":"authorization","in":"header","required":false,"schema":{"type":"string","title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/chats/{chat_id}/messages":{"delete":{"summary":"Clear Chat","description":"\"Clear all history\" in the app: every message after the greeting is\ndeleted, so the assistant no longer reads them and another device doesn't\nbring them back. The greeting stays, as it does in the app.","operationId":"clear_chat_v1_chats__chat_id__messages_delete","parameters":[{"name":"chat_id","in":"path","required":true,"schema":{"type":"string","title":"Chat Id"}},{"name":"authorization","in":"header","required":false,"schema":{"type":"string","title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"summary":"Post Message","operationId":"post_message_v1_chats__chat_id__messages_post","parameters":[{"name":"chat_id","in":"path","required":true,"schema":{"type":"string","title":"Chat Id"}},{"name":"authorization","in":"header","required":false,"schema":{"type":"string","title":"Authorization"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Body"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/chats/{chat_id}/messages/photo":{"post":{"summary":"Post Message Photo","description":"Photo counterpart of POST /v1/chats/{chat_id}/messages. The text\nendpoint takes a JSON body and never actually looks at image_url content\n-- it only tells the (text-only) model to \"acknowledge\" it. Chat photos\nneed real vision analysis (the same quality as /v1/identify), so this is\na separate multipart endpoint: it saves the photo under /static (see\n_save_chat_photo), sends it to Gemini as an inlineData vision part, and\nthreads it into the same per-chat DB history as text messages so a\nphoto exchange isn't invisible to the next turn.","operationId":"post_message_photo_v1_chats__chat_id__messages_photo_post","parameters":[{"name":"chat_id","in":"path","required":true,"schema":{"type":"string","title":"Chat Id"}},{"name":"authorization","in":"header","required":false,"schema":{"type":"string","title":"Authorization"}}],"requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/Body_post_message_photo_v1_chats__chat_id__messages_photo_post"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/chat":{"post":{"summary":"Chat","operationId":"chat_v1_chat_post","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"type":"string","title":"Authorization"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Body"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/chat/stream":{"get":{"summary":"Chat Stream","operationId":"chat_stream_v1_chat_stream_get","parameters":[{"name":"text","in":"query","required":true,"schema":{"type":"string","title":"Text"}},{"name":"authorization","in":"header","required":false,"schema":{"type":"string","title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/care/pot":{"get":{"summary":"Care Pot","description":"Starting pot for the water calculator opened from a plant: sized for\nthe plant's type instead of the generic 15×15 cm. Unknown size → nulls\n(the app keeps its default), never a guess.","operationId":"care_pot_v1_care_pot_get","parameters":[{"name":"plantId","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Plantid"}},{"name":"latin","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Latin"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"summary":"Care Pot From Photos","description":"The pot in the person's own photos of this plant (the scan's captures),\nfor the water calculator's starting sliders. `basis: \"photo\"` with the\nestimate; `basis: \"ground\"` with `spread` when the plant grows in the\nground (build 80 #2); nulls when nothing could be seen. GET /v1/care/pot\nstays the typical pot for the plant's size and type.","operationId":"care_pot_from_photos_v1_care_pot_post","requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/Body_care_pot_from_photos_v1_care_pot_post"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/season":{"get":{"summary":"Season","operationId":"season_v1_season_get","parameters":[{"name":"date","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"YYYY-MM-DD, default today","title":"Date"},"description":"YYYY-MM-DD, default today"},{"name":"lat","in":"query","required":false,"schema":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Lat"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/care/profile":{"get":{"summary":"Care Profile","description":"The plant's own care intervals (from its profile). There is no generic\nper-group table any more: unknown values are null.","operationId":"care_profile_v1_care_profile_get","parameters":[{"name":"plantId","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Plantid"}},{"name":"latin","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Latin"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/care/calculate":{"post":{"summary":"Care Calculate","operationId":"care_calculate_v1_care_calculate_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CalculateRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/schedule":{"get":{"summary":"Get Schedule","description":"Upcoming care for one plant from its own profile: watering (growing vs\nresting interval by season), fertilizing only in its feeding months,\nmisting. Topics with unknown intervals are listed in `unknown`.","operationId":"get_schedule_v1_schedule_get","parameters":[{"name":"plantId","in":"query","required":true,"schema":{"type":"string","description":"plant id","title":"Plantid"},"description":"plant id"},{"name":"days","in":"query","required":false,"schema":{"type":"integer","maximum":365,"minimum":1,"default":60,"title":"Days"}},{"name":"lat","in":"query","required":false,"schema":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Lat"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/care/log":{"post":{"summary":"Care Log","operationId":"care_log_v1_care_log_post","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Body"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"get":{"summary":"Get Care Log","operationId":"get_care_log_v1_care_log_get","parameters":[{"name":"plantId","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Plantid"}},{"name":"days","in":"query","required":false,"schema":{"type":"integer","maximum":365,"minimum":1,"default":30,"title":"Days"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/push/register":{"post":{"summary":"Push Register","operationId":"push_register_v1_push_register_post","requestBody":{"content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Body"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/push/schedule":{"get":{"summary":"Push Schedule","operationId":"push_schedule_v1_push_schedule_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/v1/vacation/plan":{"get":{"summary":"Vacation Plan","operationId":"vacation_plan_v1_vacation_plan_get","parameters":[{"name":"from","in":"query","required":true,"schema":{"type":"string","title":"From"}},{"name":"to","in":"query","required":true,"schema":{"type":"string","title":"To"}},{"name":"plantIds","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Plantids"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/care/topics":{"get":{"summary":"Care Topics","operationId":"care_topics_v1_care_topics_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/v1/user/data":{"get":{"summary":"Get User Data","operationId":"get_user_data_v1_user_data_get","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"type":"string","title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"put":{"summary":"Patch User Data","operationId":"patch_user_data_v1_user_data_put","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"type":"string","title":"Authorization"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Body"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"patch":{"summary":"Patch User Data","operationId":"patch_user_data_v1_user_data_patch","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"type":"string","title":"Authorization"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Body"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"summary":"Delete User Data","operationId":"delete_user_data_v1_user_data_delete","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"type":"string","title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/user/export":{"get":{"summary":"Export User Data","operationId":"export_user_data_v1_user_export_get","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"type":"string","title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/sync/offline-queue":{"post":{"summary":"Offline Queue","description":"Changes saved while offline: {operations: [{type: \"patch\", payload: {...}}, ...]},\napplied in order like PATCH /v1/user/data. (It used to answer \"ok\" and drop\nthem.) Current app builds send the newest copy with PATCH instead; this\nkeeps older builds' queued changes.","operationId":"offline_queue_v1_sync_offline_queue_post","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"type":"string","title":"Authorization"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Body"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/img":{"get":{"summary":"Img","operationId":"img_v1_img_get","parameters":[{"name":"u","in":"query","required":true,"schema":{"type":"string","description":"Remote image URL (allowlisted hosts only)","title":"U"},"description":"Remote image URL (allowlisted hosts only)"},{"name":"s","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Optional shorter-side size in px (fill tiles)","title":"S"},"description":"Optional shorter-side size in px (fill tiles)"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/plantimg/{plant_id}":{"get":{"summary":"Plantimg","description":"A plant's public photo from our own disk (src/plant_images.py) —\nnever expires, unlike the Perenual links it was copied from.","operationId":"plantimg_v1_plantimg__plant_id__get","parameters":[{"name":"plant_id","in":"path","required":true,"schema":{"type":"string","title":"Plant Id"}},{"name":"s","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Shorter-side size in px (snapped to the size buckets)","title":"S"},"description":"Shorter-side size in px (snapped to the size buckets)"},{"name":"w","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"description":"Tile width in px (older app builds)","title":"W"},"description":"Tile width in px (older app builds)"},{"name":"h","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"description":"Tile height in px (older app builds)","title":"H"},"description":"Tile height in px (older app builds)"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/pestimg/{key}":{"get":{"summary":"Pestimg","description":"A photo of a pest or disease (src/pest_photos.py, Oct 15 call #8).","operationId":"pestimg_v1_pestimg__key__get","parameters":[{"name":"key","in":"path","required":true,"schema":{"type":"string","title":"Key"}},{"name":"s","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Shorter-side size in px (snapped to the size buckets)","title":"S"},"description":"Shorter-side size in px (snapped to the size buckets)"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/scanimg/{plant_id}":{"get":{"summary":"Scanimg","description":"User capture(s) attached to a shared row (see identify photo-share).\n`<uuid>` serves the primary photo; `<uuid>_<md5prefix>` serves extras.\nStable forever — our own disk, never a signed URL.","operationId":"scanimg_v1_scanimg__plant_id__get","parameters":[{"name":"plant_id","in":"path","required":true,"schema":{"type":"string","title":"Plant Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/content":{"get":{"summary":"Content","operationId":"content_v1_content_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/v1/datasets":{"get":{"summary":"Datasets","operationId":"datasets_v1_datasets_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/v1/catalog/fields":{"get":{"summary":"Catalog Fields","operationId":"catalog_fields_v1_catalog_fields_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/v1/catalog/coverage":{"get":{"summary":"Catalog Coverage","operationId":"catalog_coverage_v1_catalog_coverage_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/v1/catalog/fields/{field_path}":{"get":{"summary":"Catalog Field Detail","operationId":"catalog_field_detail_v1_catalog_fields__field_path__get","parameters":[{"name":"field_path","in":"path","required":true,"schema":{"type":"string","title":"Field Path"}},{"name":"q","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Q"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":200,"minimum":1,"default":50,"title":"Limit"}},{"name":"offset","in":"query","required":false,"schema":{"type":"integer","minimum":0,"default":0,"title":"Offset"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/fill/status":{"get":{"summary":"Fill Status","description":"Public: is a fill wave running, how far did it get.","operationId":"fill_status_v1_fill_status_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/v1/fill/start":{"post":{"summary":"Fill Start","description":"Token-gated: launch a detached fill wave (refuses when one runs).","operationId":"fill_start_v1_fill_start_post","parameters":[{"name":"token","in":"query","required":false,"schema":{"type":"string","default":"","title":"Token"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":500000,"minimum":1,"default":400000,"title":"Limit"}},{"name":"rpm","in":"query","required":false,"schema":{"type":"number","maximum":100.0,"minimum":1.0,"default":12.0,"title":"Rpm"}},{"name":"workers","in":"query","required":false,"schema":{"type":"integer","maximum":8,"minimum":1,"default":2,"title":"Workers"}},{"name":"order","in":"query","required":false,"schema":{"type":"string","default":"popular","title":"Order"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/fill/stop":{"post":{"summary":"Fill Stop","description":"Token-gated: SIGTERM the running wave (progress is kept).","operationId":"fill_stop_v1_fill_stop_post","parameters":[{"name":"token","in":"query","required":false,"schema":{"type":"string","default":"","title":"Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}}},"components":{"schemas":{"AnonymousRequest":{"properties":{"deviceId":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Deviceid"}},"type":"object","title":"AnonymousRequest"},"Body_care_check_v1_care_check_post":{"properties":{"plantId":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Plantid"},"photo":{"type":"string","format":"binary","title":"Photo"}},"type":"object","required":["photo"],"title":"Body_care_check_v1_care_check_post"},"Body_care_pot_from_photos_v1_care_pot_post":{"properties":{"plantId":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Plantid"},"latin":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Latin"},"images":{"items":{"type":"string","format":"binary"},"type":"array","title":"Images"}},"type":"object","required":["images"],"title":"Body_care_pot_from_photos_v1_care_pot_post"},"Body_diagnose_v1_diagnose_post":{"properties":{"images":{"items":{"type":"string","format":"binary"},"type":"array","title":"Images","description":"1..3 leaf photos"},"plantId":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Plantid"}},"type":"object","required":["images"],"title":"Body_diagnose_v1_diagnose_post"},"Body_identify_v1_identify_post":{"properties":{"images":{"items":{"type":"string","format":"binary"},"type":"array","title":"Images","description":"1..3 JPEGs"},"scanType":{"type":"string","title":"Scantype","description":"plain|weed|allergen|toxic|tree","default":"plain"},"scan_type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Scan Type"}},"type":"object","required":["images"],"title":"Body_identify_v1_identify_post"},"Body_post_message_photo_v1_chats__chat_id__messages_photo_post":{"properties":{"image":{"type":"string","format":"binary","title":"Image"},"text":{"type":"string","title":"Text","default":""},"city":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"City"},"country":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Country"},"lat":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Lat"},"lon":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Lon"}},"type":"object","required":["image"],"title":"Body_post_message_photo_v1_chats__chat_id__messages_photo_post"},"CalculateRequest":{"properties":{"potHeight":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Potheight","default":15},"potWidth":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Potwidth","default":15},"pot":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Pot"},"humidity":{"type":"number","title":"Humidity","default":50},"temperature":{"type":"number","title":"Temperature","default":20},"outdoor":{"type":"boolean","title":"Outdoor","default":false},"inGround":{"type":"boolean","title":"Inground","default":false},"spread":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Spread"},"lat":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Lat"},"date":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Date"},"plantId":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Plantid"},"latin":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Latin"}},"type":"object","title":"CalculateRequest"},"HTTPValidationError":{"properties":{"detail":{"items":{"$ref":"#/components/schemas/ValidationError"},"type":"array","title":"Detail"}},"type":"object","title":"HTTPValidationError"},"RefreshRequest":{"properties":{"refreshToken":{"type":"string","title":"Refreshtoken"}},"type":"object","required":["refreshToken"],"title":"RefreshRequest"},"ValidationError":{"properties":{"loc":{"items":{"anyOf":[{"type":"string"},{"type":"integer"}]},"type":"array","title":"Location"},"msg":{"type":"string","title":"Message"},"type":{"type":"string","title":"Error Type"}},"type":"object","required":["loc","msg","type"],"title":"ValidationError"}}}}