{"openapi":"3.1.0","info":{"title":"Peppula Coat Intelligence API","description":"Headless API for pet businesses. One photo of a dog → structured coat analysis with breed detection, condition scoring, tool recommendations, and wellness flags.\n\n**Two tiers:**\n- **Coat Score** — fast breed + coat + conditions + matting zones\n- **Full Intelligence** — everything + tools with SKU mapping + styles + wellness\n\nPlus atomic endpoints for health flags, grooming kit, styles, and matting zones.","contact":{"url":"https://peppula.com/","email":"api@peppula.com"},"version":"1.0.0"},"paths":{"/v1/tracking/assess":{"post":{"tags":["Coat Tracking"],"summary":"Track a dog assessment — run inference and store longitudinally","description":"Submit a dog photo for a tracked dog. Runs the full coat-intelligence pipeline (MobileCLIP + Gemini + coat type validation + matting cap) and stores the result per dog_id for longitudinal querying. Returns the assessment result plus a diff against the previous assessment and current pattern signals.","operationId":"tracking_assess_v1_tracking_assess_post","requestBody":{"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/Body_tracking_assess_v1_tracking_assess_post"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TrackingAssessResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/tracking/history":{"get":{"tags":["Coat Tracking"],"summary":"Assessment history — timeline with stats and trends","description":"Retrieve a dog's assessment history with trend data. Filter by period (1w/1m/3m/6m/1y) or explicit from/to dates. Returns timeline entries with per-entry season, condition trends, and aggregate stats.","operationId":"tracking_history_v1_tracking_history_get","parameters":[{"name":"dog_id","in":"query","required":true,"schema":{"type":"string","title":"Dog Id"}},{"name":"period","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Period"}},{"name":"from_date","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"From Date"}},{"name":"to_date","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"To Date"}},{"name":"condition_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Condition Id"}},{"name":"conditions_only","in":"query","required":false,"schema":{"type":"boolean","default":false,"title":"Conditions Only"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TrackingHistoryResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/tracking/signals":{"get":{"tags":["Coat Tracking"],"summary":"Pattern signals — condition trends with breed health flag context","description":"Get longitudinal pattern data for a dog — recurring conditions, severity trajectories, resolved conditions, and breed health flag correlations. Evidence arrays are fully dated and traceable. We return structured data — the business applies domain expertise.","operationId":"tracking_signals_v1_tracking_signals_get","parameters":[{"name":"dog_id","in":"query","required":true,"schema":{"type":"string","title":"Dog Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TrackingSignalsResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/tracking/dogs":{"get":{"tags":["Coat Tracking"],"summary":"List all tracked dogs for this API key","description":"Returns all dogs tracked under this API key with their assessment counts and active signal counts.","operationId":"tracking_dogs_v1_tracking_dogs_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TrackingDogsResponse"}}}}}}},"/v1/tracking/compare":{"get":{"tags":["Coat Tracking"],"summary":"Compare two assessments — what changed between date A and date B","description":"Dates snap to the nearest assessment on or before the given date. Returns new conditions, resolved conditions, worsening, improving, and unchanged with a summary of net change.","operationId":"tracking_compare_v1_tracking_compare_get","parameters":[{"name":"dog_id","in":"query","required":true,"schema":{"type":"string","title":"Dog Id"}},{"name":"date_a","in":"query","required":true,"schema":{"type":"string","title":"Date A"}},{"name":"date_b","in":"query","required":true,"schema":{"type":"string","title":"Date B"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CompareResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/tracking/assess/batch":{"post":{"tags":["Coat Tracking"],"summary":"Batch assess — up to 10 dogs in one request (sequential)","description":"Assess multiple dogs in one request. Each photo runs through the full pipeline sequentially (to manage Gemini rate limits). assessments field: JSON array of {dog_id, breed_override}. photos field: one file per dog, order matches assessments array. Max 10 dogs per batch.","operationId":"tracking_assess_batch_v1_tracking_assess_batch_post","requestBody":{"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/Body_tracking_assess_batch_v1_tracking_assess_batch_post"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BatchAssessResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/tracking/signals/batch":{"get":{"tags":["Coat Tracking"],"summary":"Batch signals — patterns for multiple dogs at once","description":"Get pattern signals for multiple dogs in one request. dog_ids: comma-separated list (max 50). Returns signals keyed by dog_id. Unknown dog_ids return empty patterns.","operationId":"tracking_signals_batch_v1_tracking_signals_batch_get","parameters":[{"name":"dog_ids","in":"query","required":true,"schema":{"type":"string","title":"Dog Ids"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BatchSignalsResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/dental-health":{"post":{"tags":["Vertical Health"],"summary":"Dental Health — mouth close-up analysis","description":"Upload a close-up photo of a dog's mouth/teeth. Returns dental conditions with severity scoring. For dental product companies, vet clinics, and pet insurance.","operationId":"dental_health_v1_dental_health_post","requestBody":{"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/Body_dental_health_v1_dental_health_post"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/VerticalHealthResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/eye-health":{"post":{"tags":["Vertical Health"],"summary":"Eye Health — eye close-up analysis","description":"Upload a close-up photo of a dog's eyes. Returns eye conditions with severity scoring. For vet clinics, pet insurance, and eye care products.","operationId":"eye_health_v1_eye_health_post","requestBody":{"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/Body_eye_health_v1_eye_health_post"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/VerticalHealthResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/skin-health":{"post":{"tags":["Vertical Health"],"summary":"Skin Health — skin close-up analysis","description":"Upload a close-up photo of a dog's skin area. Returns skin conditions with severity scoring. For dermatology products, medicated shampoo brands, and vet clinics.","operationId":"skin_health_v1_skin_health_post","requestBody":{"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/Body_skin_health_v1_skin_health_post"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/VerticalHealthResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/ear-health":{"post":{"tags":["Vertical Health"],"summary":"Ear Health — ear close-up analysis","description":"Upload a close-up photo of a dog's ear. Returns ear conditions with severity scoring. For ear care products, vet clinics.","operationId":"ear_health_v1_ear_health_post","requestBody":{"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/Body_ear_health_v1_ear_health_post"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/VerticalHealthResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/nail-health":{"post":{"tags":["Vertical Health"],"summary":"Nail Health — nail/claw close-up analysis","description":"Upload a close-up photo of a dog's nails. Returns nail conditions with severity scoring. For nail care products, grooming tools.","operationId":"nail_health_v1_nail_health_post","requestBody":{"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/Body_nail_health_v1_nail_health_post"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/VerticalHealthResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/paw-health":{"post":{"tags":["Vertical Health"],"summary":"Paw Health — paw pad close-up analysis","description":"Upload a close-up photo of a dog's paw pads. Returns paw conditions with severity scoring. For paw balm products, winter care, vet clinics.","operationId":"paw_health_v1_paw_health_post","requestBody":{"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/Body_paw_health_v1_paw_health_post"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/VerticalHealthResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/report/wellness":{"post":{"tags":["Reports"],"summary":"Wellness Report — consumer-ready formatted assessment","description":"Upload up to 3 photos, get a structured wellness report with sections by body area. Ready to embed in your app or email to the dog owner. Body photo for full analysis, close-up for verified severity, concern photo for flagged areas.","operationId":"wellness_report_v1_report_wellness_post","requestBody":{"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/Body_wellness_report_v1_report_wellness_post"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WellnessReport"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/coat-score":{"post":{"tags":["Coat Analysis"],"summary":"Coat Score — breed + conditions + matting zones (FAST)","description":"Upload a dog photo → get breed, coat type, conditions with severity 1-5, matting zones with risk levels. The fast, atomic endpoint.","operationId":"coat_score_v1_coat_score_post","requestBody":{"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/Body_coat_score_v1_coat_score_post"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CoatScoreResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/coat-intelligence":{"post":{"tags":["Coat Analysis"],"summary":"Full Intelligence — coat + tools + styles + wellness","description":"Everything from Coat Score, plus tool recommendations with SKU mapping, achievable styles, wellness flags, safety warnings, and care schedule.","operationId":"coat_intelligence_v1_coat_intelligence_post","requestBody":{"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/Body_coat_intelligence_v1_coat_intelligence_post"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CoatIntelligenceResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/coat-score/lookup":{"post":{"tags":["Coat Analysis — Lookup"],"summary":"Coat Score Lookup — breed + conditions → analysis (NO photo needed)","description":"Send breed and conditions as JSON. Returns the same response as /coat-score but without photo inference. Use when you already know the breed from your own system.","operationId":"coat_score_lookup_v1_coat_score_lookup_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CoatScoreLookupRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CoatScoreResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/coat-intelligence/lookup":{"post":{"tags":["Coat Analysis — Lookup"],"summary":"Full Intelligence Lookup — breed + conditions → everything (NO photo needed)","description":"Send breed and conditions as JSON. Returns the full intelligence response with tools, styles, wellness, care schedule — without photo inference.","operationId":"coat_intelligence_lookup_v1_coat_intelligence_lookup_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CoatIntelligenceLookupRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CoatIntelligenceResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/health-flags":{"post":{"tags":["Atomic Lookups"],"summary":"Health Flags — breed wellness intelligence (no photo needed)","description":"Returns breed health predispositions, wellness flags, and safety warnings. Pass condition IDs from a previous coat-score to amplify relevant flags.","operationId":"health_flags_v1_health_flags_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HealthFlagsRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HealthFlagsResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/grooming-kit":{"post":{"tags":["Atomic Lookups"],"summary":"Grooming Kit — tool recommendations with SKU mapping keys (no photo needed)","description":"Returns recommended tools for this breed + coat type + conditions. Each tool has a `sku_mapping_key` for your product catalogue integration.","operationId":"grooming_kit_v1_grooming_kit_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GroomingKitRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GroomingKitResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/style-options":{"post":{"tags":["Atomic Lookups"],"summary":"Style Options — achievable styles with blade specs (no photo needed)","description":"Returns all achievable grooming styles for this coat type, with blade numbers, rationale, and maintenance instructions.","operationId":"style_options_v1_style_options_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StyleOptionsRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StyleOptionsResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/matting-zones":{"post":{"tags":["Atomic Lookups"],"summary":"Matting Zones — breed-specific matting risk map (no photo needed)","description":"Returns breed-specific matting risk zones ranked by probability, with brushing frequency recommendations.","operationId":"matting_zones_endpoint_v1_matting_zones_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MattingZonesRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MattingZonesResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/sku-mapping-keys":{"get":{"tags":["Product Integration"],"summary":"List all available SKU mapping keys","description":"Returns all standardized tool keys that Peppula can recommend. Map these to your product SKUs via /sku-mapping.","operationId":"sku_mapping_keys_v1_sku_mapping_keys_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SkuMappingKeysResponse"}}}}}}},"/v1/sku-mapping":{"post":{"tags":["Product Integration"],"summary":"Register your product catalogue mapping","description":"Map Peppula's tool keys to your product SKUs. Merge-by-key upsert: existing keys are updated, new keys are added, unmapped keys are left unchanged. Once registered, Full Intelligence responses include your products alongside our recommendations.","operationId":"register_sku_mapping_v1_sku_mapping_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SkuMappingRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/breeds":{"get":{"tags":["Reference"],"summary":"List all 178 breeds with coat types","description":"Returns every breed in Peppula's ground truth database, verified against AKC breed standards.","operationId":"list_breeds_v1_breeds_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BreedsResponse"}}}}}}},"/v1/breeds/{breed_key}":{"get":{"tags":["Reference"],"summary":"Get single breed detail","operationId":"get_breed_v1_breeds__breed_key__get","parameters":[{"name":"breed_key","in":"path","required":true,"schema":{"type":"string","title":"Breed Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BreedEntry"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}}},"components":{"schemas":{"ActionType":{"type":"string","enum":["worth_mentioning_to_vet","routine_care","informational"],"title":"ActionType"},"AdditionalObservation":{"properties":{"observation_id":{"type":"string","title":"Observation Id","description":"Raw ID from AI (not in canonical set)"},"description":{"type":"string","title":"Description","description":"Human-readable description"},"location":{"type":"string","title":"Location","description":"Body area if applicable","default":""},"reasons_observed":{"items":{"type":"string"},"type":"array","title":"Reasons Observed","description":"What the AI saw"},"source":{"type":"string","title":"Source","description":"Which model produced this observation","default":"gemini"}},"type":"object","required":["observation_id","description"],"title":"AdditionalObservation","description":"Something the AI observed that isn't in our canonical condition set.\nInformational only — no severity scoring, no pricing impact.\nUseful for surfacing real findings that haven't been codified yet."},"BatchAssessResponse":{"properties":{"results":{"items":{"type":"object"},"type":"array","title":"Results"},"total":{"type":"integer","title":"Total","default":0},"succeeded":{"type":"integer","title":"Succeeded","default":0},"failed":{"type":"integer","title":"Failed","default":0}},"type":"object","title":"BatchAssessResponse","description":"Response from POST /v1/tracking/assess/batch."},"BatchSignalsResponse":{"properties":{"dogs":{"type":"object","title":"Dogs"},"total_dogs":{"type":"integer","title":"Total Dogs","default":0},"total_patterns":{"type":"integer","title":"Total Patterns","default":0}},"type":"object","title":"BatchSignalsResponse","description":"Response from GET /v1/tracking/signals/batch."},"Body_coat_intelligence_v1_coat_intelligence_post":{"properties":{"photo":{"type":"string","format":"binary","title":"Photo","description":"Body photo"},"photo_hotspot":{"anyOf":[{"type":"string","format":"binary"},{"type":"null"}],"title":"Photo Hotspot","description":"Close-up of matted/problem area"},"photo_concern":{"anyOf":[{"type":"string","format":"binary"},{"type":"null"}],"title":"Photo Concern","description":"Photo of a specific concern"},"breed_override":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Breed Override"},"country":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Country"},"postal_code":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Postal Code"}},"type":"object","required":["photo"],"title":"Body_coat_intelligence_v1_coat_intelligence_post"},"Body_coat_score_v1_coat_score_post":{"properties":{"photo":{"type":"string","format":"binary","title":"Photo","description":"Body photo (JPEG, PNG, WebP, max 10MB)"},"photo_hotspot":{"anyOf":[{"type":"string","format":"binary"},{"type":"null"}],"title":"Photo Hotspot","description":"Close-up of matted/problem area. Overrides body-photo matting cap."},"photo_concern":{"anyOf":[{"type":"string","format":"binary"},{"type":"null"}],"title":"Photo Concern","description":"Photo of a specific concern the owner flagged."},"breed_override":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Breed Override","description":"Skip AI breed detection"}},"type":"object","required":["photo"],"title":"Body_coat_score_v1_coat_score_post"},"Body_dental_health_v1_dental_health_post":{"properties":{"photo":{"type":"string","format":"binary","title":"Photo","description":"Mouth/teeth close-up photo"},"breed":{"type":"string","title":"Breed","description":"Dog breed (required — no breed detection on close-ups)"},"dog_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Dog Id","description":"Your dog identifier. If not provided, one is auto-generated."},"postal_code":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Postal Code","description":"Customer's postal code for geographic insights"},"country":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Country","description":"2-letter country code (e.g., BE, US, NL)"}},"type":"object","required":["photo","breed"],"title":"Body_dental_health_v1_dental_health_post"},"Body_ear_health_v1_ear_health_post":{"properties":{"photo":{"type":"string","format":"binary","title":"Photo","description":"Ear close-up photo"},"breed":{"type":"string","title":"Breed","description":"Dog breed (required)"},"dog_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Dog Id","description":"Your dog identifier. If not provided, one is auto-generated."},"postal_code":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Postal Code","description":"Customer's postal code for geographic insights"},"country":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Country","description":"2-letter country code (e.g., BE, US, NL)"}},"type":"object","required":["photo","breed"],"title":"Body_ear_health_v1_ear_health_post"},"Body_eye_health_v1_eye_health_post":{"properties":{"photo":{"type":"string","format":"binary","title":"Photo","description":"Eye close-up photo"},"breed":{"type":"string","title":"Breed","description":"Dog breed (required)"},"dog_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Dog Id","description":"Your dog identifier. If not provided, one is auto-generated."},"postal_code":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Postal Code","description":"Customer's postal code for geographic insights"},"country":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Country","description":"2-letter country code (e.g., BE, US, NL)"}},"type":"object","required":["photo","breed"],"title":"Body_eye_health_v1_eye_health_post"},"Body_nail_health_v1_nail_health_post":{"properties":{"photo":{"type":"string","format":"binary","title":"Photo","description":"Nail/claw close-up photo"},"breed":{"type":"string","title":"Breed","description":"Dog breed (required)"},"dog_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Dog Id","description":"Your dog identifier. If not provided, one is auto-generated."},"postal_code":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Postal Code","description":"Customer's postal code for geographic insights"},"country":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Country","description":"2-letter country code (e.g., BE, US, NL)"}},"type":"object","required":["photo","breed"],"title":"Body_nail_health_v1_nail_health_post"},"Body_paw_health_v1_paw_health_post":{"properties":{"photo":{"type":"string","format":"binary","title":"Photo","description":"Paw pad close-up photo"},"breed":{"type":"string","title":"Breed","description":"Dog breed (required)"},"dog_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Dog Id","description":"Your dog identifier. If not provided, one is auto-generated."},"postal_code":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Postal Code","description":"Customer's postal code for geographic insights"},"country":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Country","description":"2-letter country code (e.g., BE, US, NL)"}},"type":"object","required":["photo","breed"],"title":"Body_paw_health_v1_paw_health_post"},"Body_skin_health_v1_skin_health_post":{"properties":{"photo":{"type":"string","format":"binary","title":"Photo","description":"Skin close-up photo"},"breed":{"type":"string","title":"Breed","description":"Dog breed (required)"},"dog_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Dog Id","description":"Your dog identifier. If not provided, one is auto-generated."},"postal_code":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Postal Code","description":"Customer's postal code for geographic insights"},"country":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Country","description":"2-letter country code (e.g., BE, US, NL)"}},"type":"object","required":["photo","breed"],"title":"Body_skin_health_v1_skin_health_post"},"Body_tracking_assess_batch_v1_tracking_assess_batch_post":{"properties":{"assessments":{"type":"string","title":"Assessments","description":"JSON array: [{\"dog_id\": \"...\", \"breed_override\": null}]"},"photos":{"items":{"type":"string","format":"binary"},"type":"array","title":"Photos","description":"One photo per dog, order matches assessments array"}},"type":"object","required":["assessments","photos"],"title":"Body_tracking_assess_batch_v1_tracking_assess_batch_post"},"Body_tracking_assess_v1_tracking_assess_post":{"properties":{"photo":{"type":"string","format":"binary","title":"Photo","description":"Body photo (JPEG, PNG, WebP, max 10MB)"},"photo_hotspot":{"anyOf":[{"type":"string","format":"binary"},{"type":"null"}],"title":"Photo Hotspot","description":"Close-up of matted/problem area"},"photo_concern":{"anyOf":[{"type":"string","format":"binary"},{"type":"null"}],"title":"Photo Concern","description":"Photo of specific concern"},"dog_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Dog Id","description":"Your dog identifier. If not provided, one is auto-generated (prefix 'auto_')."},"dog_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Dog Name","description":"Dog's name (for display)"},"breed_override":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Breed Override","description":"Skip AI breed detection"},"postal_code":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Postal Code","description":"Customer's postal code for geographic insights"},"country":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Country","description":"2-letter country code (e.g., BE, US, NL)"}},"type":"object","required":["photo"],"title":"Body_tracking_assess_v1_tracking_assess_post"},"Body_wellness_report_v1_report_wellness_post":{"properties":{"photo":{"type":"string","format":"binary","title":"Photo","description":"Body photo (required)"},"photo_hotspot":{"anyOf":[{"type":"string","format":"binary"},{"type":"null"}],"title":"Photo Hotspot","description":"Close-up of matted/problem area"},"photo_concern":{"anyOf":[{"type":"string","format":"binary"},{"type":"null"}],"title":"Photo Concern","description":"Photo of a specific concern"},"breed_override":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Breed Override"},"dog_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Dog Id","description":"Dog ID — if provided, includes tracking summary"},"dog_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Dog Name"}},"type":"object","required":["photo"],"title":"Body_wellness_report_v1_report_wellness_post"},"BreedContext":{"properties":{"health_flags":{"items":{"type":"string"},"type":"array","title":"Health Flags"},"correlations":{"items":{"$ref":"#/components/schemas/BreedCorrelation"},"type":"array","title":"Correlations"}},"type":"object","title":"BreedContext","description":"Breed health flags and condition correlations for this dog."},"BreedContextSection":{"properties":{"breed":{"type":"string","title":"Breed"},"breed_display_name":{"type":"string","title":"Breed Display Name"},"coat_type":{"type":"string","title":"Coat Type"},"size":{"type":"string","title":"Size"},"health_flags":{"items":{"type":"string"},"type":"array","title":"Health Flags"},"health_flag_descriptions":{"items":{"type":"object"},"type":"array","title":"Health Flag Descriptions"}},"type":"object","required":["breed","breed_display_name","coat_type","size"],"title":"BreedContextSection","description":"Breed information section of the report."},"BreedCorrelation":{"properties":{"condition":{"type":"string","title":"Condition"},"flag":{"type":"string","title":"Flag"}},"type":"object","required":["condition","flag"],"title":"BreedCorrelation","description":"A correlation between a condition and a breed health flag."},"BreedEntry":{"properties":{"key":{"type":"string","title":"Key"},"name":{"type":"string","title":"Name"},"coat_type":{"$ref":"#/components/schemas/CoatType"},"size":{"$ref":"#/components/schemas/BreedSize"},"health_flags":{"items":{"type":"string"},"type":"array","title":"Health Flags"}},"type":"object","required":["key","name","coat_type","size"],"title":"BreedEntry","description":"A single breed in the breeds reference."},"BreedSize":{"type":"string","enum":["tiny","small","medium","large","giant"],"title":"BreedSize"},"BreedsResponse":{"properties":{"total":{"type":"integer","title":"Total"},"breeds":{"items":{"$ref":"#/components/schemas/BreedEntry"},"type":"array","title":"Breeds"}},"type":"object","required":["total","breeds"],"title":"BreedsResponse","description":"Response from /breeds — all breeds reference."},"CacheHitType":{"type":"string","enum":["exact","breed_cached","none"],"title":"CacheHitType"},"CareSchedule":{"properties":{"brush_frequency":{"type":"string","title":"Brush Frequency","description":"e.g., 'Every 1-2 days; daily during shedding season'","default":""},"professional_groom_interval_weeks":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Professional Groom Interval Weeks"},"deshed_interval_weeks":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Deshed Interval Weeks"},"ear_check":{"type":"string","title":"Ear Check","default":""},"nail_trim_weeks":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Nail Trim Weeks"}},"type":"object","title":"CareSchedule","description":"Recommended care schedule for this breed and coat type."},"CoatAnalysis":{"properties":{"breed":{"type":"string","title":"Breed","description":"Detected breed key (e.g., 'golden_retriever', 'poodle_standard')"},"breed_display_name":{"type":"string","title":"Breed Display Name","description":"Human-readable breed name (e.g., 'Golden Retriever')","default":""},"breed_confidence":{"type":"number","maximum":1.0,"minimum":0.0,"title":"Breed Confidence","description":"Confidence score for breed detection"},"breed_reasoning":{"type":"string","title":"Breed Reasoning","description":"1-2 sentences explaining the visual markers that confirm this breed. E.g., 'Fox-like face with erect triangular ears, curled tail, compact square build consistent with Shiba Inu.'","default":""},"coat_type":{"$ref":"#/components/schemas/CoatType"},"coat_type_confidence":{"$ref":"#/components/schemas/CoatTypeConfidence","description":"validated = matches breed ground truth (178 breeds). overridden = Gemini disagreed with ground truth, ground truth used. unverified = breed not in ground truth."},"coat_color":{"type":"string","title":"Coat Color","description":"Primary coat color(s) and pattern. E.g., 'gold', 'black and tan', 'blue merle with white chest', 'tricolor'. Used for breed verification and progressive graying detection.","default":""},"size":{"$ref":"#/components/schemas/BreedSize"}},"type":"object","required":["breed","breed_confidence","coat_type","coat_type_confidence","size"],"title":"CoatAnalysis","description":"Core breed + coat type detection result."},"CoatIntelligenceLookupRequest":{"properties":{"breed":{"type":"string","title":"Breed","description":"Breed key (e.g., 'golden_retriever')"},"coat_type":{"anyOf":[{"$ref":"#/components/schemas/CoatType"},{"type":"null"}],"description":"Override coat type if known. If omitted, looked up from breed."},"conditions":{"items":{"type":"object"},"type":"array","title":"Conditions","description":"Conditions with severity. Each: {condition_id, severity_score (1-5), location}"},"country":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Country","description":"2-letter country code"},"postal_code":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Postal Code","description":"Postal code"}},"type":"object","required":["breed"],"title":"CoatIntelligenceLookupRequest","description":"Request for /coat-intelligence/lookup — JSON mode, full response."},"CoatIntelligenceResponse":{"properties":{"request_id":{"type":"string","title":"Request Id"},"processing_time_ms":{"type":"integer","title":"Processing Time Ms"},"cache_hit":{"$ref":"#/components/schemas/CacheHitType","default":"none"},"coat_analysis":{"$ref":"#/components/schemas/CoatAnalysis"},"wellness_indicator":{"anyOf":[{"$ref":"#/components/schemas/WellnessIndicator"},{"type":"null"}],"description":"Traffic-light wellness triage"},"conditions":{"items":{"$ref":"#/components/schemas/Condition"},"type":"array","title":"Conditions"},"additional_observations":{"items":{"$ref":"#/components/schemas/AdditionalObservation"},"type":"array","title":"Additional Observations","description":"Things the AI observed that aren't in our canonical condition set. Informational only — no severity, no pricing impact."},"matting_zones":{"items":{"$ref":"#/components/schemas/MattingZone"},"type":"array","title":"Matting Zones"},"photo_quality":{"$ref":"#/components/schemas/PhotoQuality"},"dual_opinion":{"anyOf":[{"$ref":"#/components/schemas/DualOpinion"},{"type":"null"}],"description":"Structured signal from dual-opinion system. Present when MC condition classifier is loaded."},"recommended_tools":{"items":{"$ref":"#/components/schemas/RecommendedTool"},"type":"array","title":"Recommended Tools"},"style_options":{"items":{"$ref":"#/components/schemas/StyleOption"},"type":"array","title":"Style Options"},"wellness_flags":{"items":{"$ref":"#/components/schemas/WellnessFlag"},"type":"array","title":"Wellness Flags"},"safety_warnings":{"items":{"$ref":"#/components/schemas/SafetyWarning"},"type":"array","title":"Safety Warnings"},"care_schedule":{"anyOf":[{"$ref":"#/components/schemas/CareSchedule"},{"type":"null"}]}},"type":"object","required":["request_id","processing_time_ms","coat_analysis","photo_quality"],"title":"CoatIntelligenceResponse","description":"Response from /coat-intelligence — the full premium response."},"CoatScoreLookupRequest":{"properties":{"breed":{"type":"string","title":"Breed","description":"Breed key (e.g., 'golden_retriever')"},"coat_type":{"anyOf":[{"$ref":"#/components/schemas/CoatType"},{"type":"null"}],"description":"Override coat type if known. If omitted, looked up from breed."},"conditions":{"items":{"type":"object"},"type":"array","title":"Conditions","description":"Conditions with severity. Each: {condition_id, severity_score (1-5), location}"}},"type":"object","required":["breed"],"title":"CoatScoreLookupRequest","description":"Request for /coat-score/lookup — JSON mode, no photo needed.\nPet company already knows the breed and conditions from their own system."},"CoatScoreResponse":{"properties":{"request_id":{"type":"string","title":"Request Id"},"processing_time_ms":{"type":"integer","title":"Processing Time Ms"},"cache_hit":{"$ref":"#/components/schemas/CacheHitType","default":"none"},"coat_analysis":{"$ref":"#/components/schemas/CoatAnalysis"},"wellness_indicator":{"anyOf":[{"$ref":"#/components/schemas/WellnessIndicator"},{"type":"null"}],"description":"Traffic-light wellness triage"},"conditions":{"items":{"$ref":"#/components/schemas/Condition"},"type":"array","title":"Conditions"},"additional_observations":{"items":{"$ref":"#/components/schemas/AdditionalObservation"},"type":"array","title":"Additional Observations","description":"Things the AI observed that aren't in our canonical condition set. Informational only — no severity, no pricing impact."},"matting_zones":{"items":{"$ref":"#/components/schemas/MattingZone"},"type":"array","title":"Matting Zones"},"photo_quality":{"$ref":"#/components/schemas/PhotoQuality"},"dual_opinion":{"anyOf":[{"$ref":"#/components/schemas/DualOpinion"},{"type":"null"}],"description":"Structured signal from dual-opinion system. Present when MC condition classifier is loaded."}},"type":"object","required":["request_id","processing_time_ms","coat_analysis","photo_quality"],"title":"CoatScoreResponse","description":"Response from /coat-score — the fast, atomic coat analysis."},"CoatType":{"type":"string","enum":["smooth","double","wire","curly","long_silky","long_coarse","corded","hairless"],"title":"CoatType"},"CoatTypeConfidence":{"type":"string","enum":["validated","overridden","unverified"],"title":"CoatTypeConfidence"},"CompareResponse":{"properties":{"dog_id":{"type":"string","title":"Dog Id"},"date_a":{"type":"string","title":"Date A"},"date_b":{"type":"string","title":"Date B"},"days_between":{"type":"integer","title":"Days Between"},"new_conditions":{"items":{"type":"object"},"type":"array","title":"New Conditions"},"resolved_conditions":{"items":{"type":"object"},"type":"array","title":"Resolved Conditions"},"worsening":{"items":{"type":"object"},"type":"array","title":"Worsening"},"improving":{"items":{"type":"object"},"type":"array","title":"Improving"},"unchanged":{"items":{"type":"object"},"type":"array","title":"Unchanged"},"summary":{"type":"object","title":"Summary"}},"type":"object","required":["dog_id","date_a","date_b","days_between"],"title":"CompareResponse","description":"Response from GET /v1/tracking/compare."},"Condition":{"properties":{"condition_id":{"type":"string","title":"Condition Id","description":"Canonical condition ID from Peppula vocabulary"},"severity_score":{"type":"integer","maximum":5.0,"minimum":1.0,"title":"Severity Score","description":"1=minimal, 2=mild, 3=moderate, 4=severe, 5=critical"},"severity_label":{"$ref":"#/components/schemas/SeverityLabel"},"location":{"type":"string","title":"Location","description":"Body area (e.g., 'behind_ears', 'lower_legs', 'full_body')"},"confidence":{"type":"number","maximum":1.0,"minimum":0.0,"title":"Confidence","description":"Detection confidence"},"reasons_observed":{"items":{"type":"string"},"type":"array","title":"Reasons Observed","description":"What the AI observed in THIS specific photo. Changes per photo."},"reasons_criteria":{"items":{"type":"string"},"type":"array","title":"Reasons Criteria","description":"What this severity score means per professional grooming standards. Deterministic — same score always returns same criteria."},"what_it_means":{"anyOf":[{"$ref":"#/components/schemas/I18nText"},{"type":"null"}],"description":"Plain language explanation for the owner. Trilingual."}},"type":"object","required":["condition_id","severity_score","severity_label","location","confidence"],"title":"Condition","description":"A detected coat or skin condition with severity scoring and evidence."},"ConditionChange":{"properties":{"condition_id":{"type":"string","title":"Condition Id"},"previous_severity":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Previous Severity"},"current_severity":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Current Severity"},"location":{"type":"string","title":"Location","default":""}},"type":"object","required":["condition_id"],"title":"ConditionChange","description":"A condition that changed between two assessments."},"DualOpinion":{"properties":{"agreement":{"type":"string","title":"Agreement","description":"agree_disease (both detect issue), agree_healthy (both say clean), mc_soft_flag (MC flagged, Gemini didn't in MC's domain), gemini_only (Gemini found conditions MC missed or outside MC's domain), mc_unavailable (classifier not loaded)"},"domain":{"type":"string","title":"Domain","description":"in_domain (Gemini conditions are within MC's training: skin/eye), out_of_domain (dental/ear/nail/paw — MC has no opinion), mixed (both in and out), none (no conditions detected)"},"mc_flag":{"type":"boolean","title":"Mc Flag","description":"True when MC detected a concern that Gemini missed within MC's trained domain. Business action: consider showing a vet-check recommendation.","default":false},"mc_class":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Mc Class","description":"MC classifier prediction (e.g., 'demodicosis', 'eye_cataract', 'Healthy'). Only meaningful within MC's domain (skin + eye)."}},"type":"object","required":["agreement","domain"],"title":"DualOpinion","description":"Structured signal from the dual-opinion system (MC classifier + Gemini).\nBusinesses use this to decide how to act on disagreements."},"EvidencePoint":{"properties":{"date":{"type":"string","title":"Date","description":"ISO 8601 date (e.g., 2026-09-07)"},"season":{"type":"string","title":"Season","description":"spring, summer, autumn, winter"},"severity_score":{"anyOf":[{"type":"integer","maximum":5.0,"minimum":1.0},{"type":"null"}],"title":"Severity Score","description":"null = condition not detected (resolved)"},"location":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Location"}},"type":"object","required":["date","season"],"title":"EvidencePoint","description":"A single dated observation of a condition."},"GroomingKitRequest":{"properties":{"breed":{"type":"string","title":"Breed"},"coat_type":{"$ref":"#/components/schemas/CoatType"},"conditions":{"items":{"type":"string"},"type":"array","title":"Conditions"},"style_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Style Id","description":"If a style is already chosen, return tools for that style"}},"type":"object","required":["breed","coat_type"],"title":"GroomingKitRequest","description":"Request for /grooming-kit endpoint."},"GroomingKitResponse":{"properties":{"request_id":{"type":"string","title":"Request Id"},"breed":{"type":"string","title":"Breed"},"coat_type":{"$ref":"#/components/schemas/CoatType"},"recommended_tools":{"items":{"$ref":"#/components/schemas/RecommendedTool"},"type":"array","title":"Recommended Tools"},"safety_warnings":{"items":{"$ref":"#/components/schemas/SafetyWarning"},"type":"array","title":"Safety Warnings"}},"type":"object","required":["request_id","breed","coat_type"],"title":"GroomingKitResponse","description":"Response from /grooming-kit — tool recommendations."},"HTTPValidationError":{"properties":{"detail":{"items":{"$ref":"#/components/schemas/ValidationError"},"type":"array","title":"Detail"}},"type":"object","title":"HTTPValidationError"},"HealthFlagsRequest":{"properties":{"breed":{"type":"string","title":"Breed","description":"Breed key (e.g., 'golden_retriever')"},"coat_type":{"anyOf":[{"$ref":"#/components/schemas/CoatType"},{"type":"null"}],"description":"Override coat type if known"},"conditions":{"items":{"type":"string"},"type":"array","title":"Conditions","description":"Condition IDs from a previous coat-score call — amplifies relevant flags"}},"type":"object","required":["breed"],"title":"HealthFlagsRequest","description":"Request for /health-flags endpoint. No photo needed — breed-based lookup."},"HealthFlagsResponse":{"properties":{"request_id":{"type":"string","title":"Request Id"},"breed":{"type":"string","title":"Breed"},"coat_type":{"$ref":"#/components/schemas/CoatType"},"wellness_flags":{"items":{"$ref":"#/components/schemas/WellnessFlag"},"type":"array","title":"Wellness Flags"},"safety_warnings":{"items":{"$ref":"#/components/schemas/SafetyWarning"},"type":"array","title":"Safety Warnings"},"care_schedule":{"anyOf":[{"$ref":"#/components/schemas/CareSchedule"},{"type":"null"}]}},"type":"object","required":["request_id","breed","coat_type"],"title":"HealthFlagsResponse","description":"Response from /health-flags — breed wellness intelligence."},"I18nText":{"properties":{"en":{"type":"string","title":"En"},"nl":{"type":"string","title":"Nl","default":""},"fr":{"type":"string","title":"Fr","default":""}},"type":"object","required":["en"],"title":"I18nText","description":"Trilingual text (EN/NL/FR)."},"MattingZone":{"properties":{"zone":{"type":"string","title":"Zone","description":"Body area (e.g., 'behind_ears', 'armpits')"},"risk_level":{"type":"integer","maximum":5.0,"minimum":1.0,"title":"Risk Level","description":"How prone this zone is to matting for this breed"},"status":{"$ref":"#/components/schemas/MattingZoneStatus"},"brush_frequency":{"type":"string","title":"Brush Frequency","description":"Recommended brushing frequency (e.g., 'daily', 'every_2_days')","default":""}},"type":"object","required":["zone","risk_level","status"],"title":"MattingZone","description":"A breed-specific body zone with matting risk level and current status."},"MattingZoneStatus":{"type":"string","enum":["condition_detected","clear","not_visible"],"title":"MattingZoneStatus"},"MattingZonesRequest":{"properties":{"breed":{"type":"string","title":"Breed"},"coat_type":{"anyOf":[{"$ref":"#/components/schemas/CoatType"},{"type":"null"}]},"conditions":{"items":{"type":"string"},"type":"array","title":"Conditions"}},"type":"object","required":["breed"],"title":"MattingZonesRequest","description":"Request for /matting-zones endpoint."},"MattingZonesResponse":{"properties":{"request_id":{"type":"string","title":"Request Id"},"breed":{"type":"string","title":"Breed"},"coat_type":{"anyOf":[{"$ref":"#/components/schemas/CoatType"},{"type":"null"}]},"matting_zones":{"items":{"$ref":"#/components/schemas/MattingZone"},"type":"array","title":"Matting Zones"},"brush_frequency":{"type":"string","title":"Brush Frequency","default":""},"technique":{"type":"string","title":"Technique","default":""}},"type":"object","required":["request_id","breed"],"title":"MattingZonesResponse","description":"Response from /matting-zones — breed-specific matting risk map."},"Pattern":{"properties":{"signal_type":{"type":"string","title":"Signal Type","description":"recurring_condition, worsening, new_condition, resolved_condition"},"condition_id":{"type":"string","title":"Condition Id"},"severity_trend":{"type":"string","title":"Severity Trend","description":"improving, stable, worsening, new"},"occurrences":{"type":"integer","title":"Occurrences","default":0},"first_seen_at":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"First Seen At"},"last_seen_at":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Last Seen At"},"breed_flag":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Breed Flag"},"velocity":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Velocity","description":"Change rate per month. Positive = getting worse. Negative = getting better. Zero = stable. Null = not enough data."},"velocity_unit":{"type":"string","title":"Velocity Unit","default":"severity_change_per_month"},"evidence":{"items":{"$ref":"#/components/schemas/EvidencePoint"},"type":"array","title":"Evidence"}},"type":"object","required":["signal_type","condition_id","severity_trend"],"title":"Pattern","description":"A detected pattern from longitudinal data."},"PhotoCoverage":{"type":"string","enum":["full_body","partial","head_only"],"title":"PhotoCoverage"},"PhotoQuality":{"properties":{"coverage":{"$ref":"#/components/schemas/PhotoCoverage"},"areas_not_visible":{"type":"string","title":"Areas Not Visible","description":"Body areas not visible (e.g., 'hind legs, tail, belly')","default":""},"quality_warning":{"type":"boolean","title":"Quality Warning","description":"True if photo quality may affect accuracy","default":false}},"type":"object","required":["coverage"],"title":"PhotoQuality","description":"Assessment of the input photo quality and coverage."},"RecommendedTool":{"properties":{"tool_type":{"type":"string","title":"Tool Type","description":"Tool category (e.g., 'slicker_brush', 'undercoat_rake', 'blade_7F')"},"spec":{"type":"string","title":"Spec","description":"Tool specification (e.g., 'medium_stiffness', 'rotating_tooth_large')"},"body_area":{"type":"string","title":"Body Area","description":"Which body area this tool is for"},"reason":{"type":"string","title":"Reason","description":"Why this tool is recommended — owner-readable"},"priority":{"type":"integer","minimum":1.0,"title":"Priority","description":"Priority order (1 = most important)"},"sku_mapping_key":{"type":"string","title":"Sku Mapping Key","description":"Standardized key for your product catalogue mapping. Map this to your SKU via /sku-mapping endpoint."},"category":{"$ref":"#/components/schemas/ToolCategory","default":"other"},"source":{"type":"string","title":"Source","description":"Professional source that validates this recommendation","default":""},"vendor_product":{"anyOf":[{"$ref":"#/components/schemas/VendorProduct"},{"type":"null"}],"description":"Your mapped product for this tool key. Only present after you register your catalogue via POST /v1/sku-mapping."}},"type":"object","required":["tool_type","spec","body_area","reason","priority","sku_mapping_key"],"title":"RecommendedTool","description":"A tool recommendation with SKU mapping key for product catalogue integration."},"ReportSection":{"properties":{"area":{"type":"string","title":"Area","description":"coat, skin, dental, eye, ear, nail, paw"},"title":{"type":"string","title":"Title","description":"Display title: Coat Health, Skin Health, etc."},"conditions_found":{"type":"integer","title":"Conditions Found","default":0},"conditions":{"items":{"type":"object"},"type":"array","title":"Conditions"},"summary":{"type":"string","title":"Summary","default":""}},"type":"object","required":["area","title"],"title":"ReportSection","description":"A section in the wellness report."},"SafetyWarning":{"properties":{"warning":{"type":"string","title":"Warning"},"severity":{"$ref":"#/components/schemas/WarningSeverity"},"detail":{"type":"string","title":"Detail","default":""},"source":{"type":"string","title":"Source","default":""}},"type":"object","required":["warning","severity"],"title":"SafetyWarning","description":"A safety warning relevant to this breed or coat condition."},"SeverityLabel":{"type":"string","enum":["minimal","mild","moderate","severe","critical"],"title":"SeverityLabel"},"SinceLastAssessment":{"properties":{"days_since":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Days Since"},"new_conditions":{"items":{"type":"string"},"type":"array","title":"New Conditions"},"resolved_conditions":{"items":{"type":"string"},"type":"array","title":"Resolved Conditions"},"worsening":{"items":{"$ref":"#/components/schemas/ConditionChange"},"type":"array","title":"Worsening"},"improving":{"items":{"$ref":"#/components/schemas/ConditionChange"},"type":"array","title":"Improving"}},"type":"object","title":"SinceLastAssessment","description":"What changed since the previous assessment for this dog."},"SkuMappingEntry":{"properties":{"sku_mapping_key":{"type":"string","title":"Sku Mapping Key","description":"Peppula's standardized key (e.g., 'slicker_brush_medium')"},"product_sku":{"type":"string","title":"Product Sku"},"product_name":{"type":"string","title":"Product Name"},"price":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Price"},"currency":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Currency"},"url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Url"},"image_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Image Url"}},"type":"object","required":["sku_mapping_key","product_sku","product_name"],"title":"SkuMappingEntry","description":"A single product-to-key mapping."},"SkuMappingKeyEntry":{"properties":{"key":{"type":"string","title":"Key"},"description":{"type":"string","title":"Description"},"category":{"$ref":"#/components/schemas/ToolCategory"}},"type":"object","required":["key","description","category"],"title":"SkuMappingKeyEntry","description":"A single SKU mapping key with description."},"SkuMappingKeysResponse":{"properties":{"keys":{"items":{"$ref":"#/components/schemas/SkuMappingKeyEntry"},"type":"array","title":"Keys"}},"type":"object","required":["keys"],"title":"SkuMappingKeysResponse","description":"Response from /sku-mapping-keys — all available mapping keys."},"SkuMappingRequest":{"properties":{"mappings":{"items":{"$ref":"#/components/schemas/SkuMappingEntry"},"type":"array","title":"Mappings"}},"type":"object","required":["mappings"],"title":"SkuMappingRequest","description":"Request for /sku-mapping endpoint."},"StyleOption":{"properties":{"style_id":{"type":"string","title":"Style Id"},"style_name":{"type":"string","title":"Style Name"},"available":{"type":"boolean","title":"Available","description":"Whether this style is achievable given current coat condition"},"unavailable_reason":{"type":"string","title":"Unavailable Reason","description":"Why not available (e.g., 'Severe matting — shave-down first')","default":""},"blade":{"type":"string","title":"Blade","description":"Blade number (e.g., '#5F', '#7F')","default":""},"blade_mm":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Blade Mm","description":"Cut length in millimeters"},"blade_verplanck":{"type":"string","title":"Blade Verplanck","description":"Verplanck reference blade spec (professional education)","default":""},"technique":{"$ref":"#/components/schemas/Technique","default":"clipper"},"blade_rationale":{"type":"string","title":"Blade Rationale","description":"Owner-readable explanation of blade choice","default":""},"owner_maintenance":{"type":"string","title":"Owner Maintenance","description":"At-home maintenance for this style","default":""}},"type":"object","required":["style_id","style_name","available"],"title":"StyleOption","description":"An achievable grooming style with blade specs."},"StyleOptionsRequest":{"properties":{"breed":{"type":"string","title":"Breed"},"coat_type":{"$ref":"#/components/schemas/CoatType"},"conditions":{"items":{"type":"string"},"type":"array","title":"Conditions"}},"type":"object","required":["breed","coat_type"],"title":"StyleOptionsRequest","description":"Request for /style-options endpoint."},"StyleOptionsResponse":{"properties":{"request_id":{"type":"string","title":"Request Id"},"breed":{"type":"string","title":"Breed"},"coat_type":{"$ref":"#/components/schemas/CoatType"},"style_options":{"items":{"$ref":"#/components/schemas/StyleOption"},"type":"array","title":"Style Options"},"safety_warnings":{"items":{"$ref":"#/components/schemas/SafetyWarning"},"type":"array","title":"Safety Warnings"}},"type":"object","required":["request_id","breed","coat_type"],"title":"StyleOptionsResponse","description":"Response from /style-options — achievable styles."},"Technique":{"type":"string","enum":["clipper","scissor","clipper_scissor","hand_strip","guard_comb_scissor","bath_brush","advanced_scissor","advanced_combination","combination"],"title":"Technique"},"TimelineCondition":{"properties":{"condition_id":{"type":"string","title":"Condition Id"},"severity_score":{"type":"integer","title":"Severity Score"},"location":{"type":"string","title":"Location","default":""},"trend":{"type":"string","title":"Trend","default":""}},"type":"object","required":["condition_id","severity_score"],"title":"TimelineCondition","description":"A condition within a timeline entry."},"TimelineEntry":{"properties":{"assessed_at":{"type":"string","title":"Assessed At"},"season":{"type":"string","title":"Season"},"conditions":{"items":{"$ref":"#/components/schemas/TimelineCondition"},"type":"array","title":"Conditions"},"additional_observations":{"items":{"type":"object"},"type":"array","title":"Additional Observations"},"max_severity":{"type":"integer","title":"Max Severity","default":0}},"type":"object","required":["assessed_at","season"],"title":"TimelineEntry","description":"A single assessment in the timeline."},"ToolCategory":{"type":"string","enum":["brush","comb","scissor","blade","spray","shampoo","conditioner","clipper_accessory","nail","ear","deshedding","other"],"title":"ToolCategory"},"TrackedDogEntry":{"properties":{"dog_id":{"type":"string","title":"Dog Id"},"name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Name"},"breed":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Breed"},"coat_type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Coat Type"},"assessment_count":{"type":"integer","title":"Assessment Count","default":0},"last_assessed_at":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Last Assessed At"},"active_signals":{"type":"integer","title":"Active Signals","default":0}},"type":"object","required":["dog_id"],"title":"TrackedDogEntry","description":"A single dog in the dogs list."},"TrackingAssessResponse":{"properties":{"request_id":{"type":"string","title":"Request Id"},"dog_id":{"type":"string","title":"Dog Id"},"dog_id_auto_generated":{"type":"boolean","title":"Dog Id Auto Generated","description":"True if we generated the dog_id. Use PUT /v1/tracking/dogs to replace with your ID.","default":false},"assessment_id":{"type":"string","title":"Assessment Id"},"assessed_at":{"type":"string","title":"Assessed At"},"assessment_number":{"type":"integer","title":"Assessment Number"},"processing_time_ms":{"type":"integer","title":"Processing Time Ms"},"cache_hit":{"$ref":"#/components/schemas/CacheHitType","default":"none"},"coat_analysis":{"$ref":"#/components/schemas/CoatAnalysis"},"conditions":{"items":{"$ref":"#/components/schemas/Condition"},"type":"array","title":"Conditions"},"additional_observations":{"items":{"$ref":"#/components/schemas/AdditionalObservation"},"type":"array","title":"Additional Observations"},"matting_zones":{"items":{"$ref":"#/components/schemas/MattingZone"},"type":"array","title":"Matting Zones"},"photo_quality":{"$ref":"#/components/schemas/PhotoQuality"},"since_last_assessment":{"anyOf":[{"$ref":"#/components/schemas/SinceLastAssessment"},{"type":"null"}]},"signals":{"items":{"$ref":"#/components/schemas/Pattern"},"type":"array","title":"Signals"}},"type":"object","required":["request_id","dog_id","assessment_id","assessed_at","assessment_number","processing_time_ms","coat_analysis","photo_quality"],"title":"TrackingAssessResponse","description":"Response from POST /v1/tracking/assess."},"TrackingDogsResponse":{"properties":{"dogs":{"items":{"$ref":"#/components/schemas/TrackedDogEntry"},"type":"array","title":"Dogs"}},"type":"object","title":"TrackingDogsResponse","description":"Response from GET /v1/tracking/dogs."},"TrackingHistoryResponse":{"properties":{"dog_id":{"type":"string","title":"Dog Id"},"breed":{"type":"string","title":"Breed"},"coat_type":{"type":"string","title":"Coat Type"},"total_assessments":{"type":"integer","title":"Total Assessments"},"period":{"type":"object","title":"Period"},"timeline":{"items":{"$ref":"#/components/schemas/TimelineEntry"},"type":"array","title":"Timeline"},"condition_summary":{"type":"object","title":"Condition Summary"},"stats":{"type":"object","title":"Stats"}},"type":"object","required":["dog_id","breed","coat_type","total_assessments","period"],"title":"TrackingHistoryResponse","description":"Response from GET /v1/tracking/history."},"TrackingSignalsResponse":{"properties":{"dog_id":{"type":"string","title":"Dog Id"},"breed":{"type":"string","title":"Breed"},"patterns":{"items":{"$ref":"#/components/schemas/Pattern"},"type":"array","title":"Patterns"},"breed_context":{"$ref":"#/components/schemas/BreedContext"}},"type":"object","required":["dog_id","breed"],"title":"TrackingSignalsResponse","description":"Response from GET /v1/tracking/signals."},"TrackingSummarySection":{"properties":{"has_history":{"type":"boolean","title":"Has History","default":false},"total_assessments":{"type":"integer","title":"Total Assessments","default":0},"last_assessed":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Last Assessed"},"improving":{"items":{"type":"string"},"type":"array","title":"Improving"},"worsening":{"items":{"type":"string"},"type":"array","title":"Worsening"},"recurring":{"items":{"type":"string"},"type":"array","title":"Recurring"},"resolved":{"items":{"type":"string"},"type":"array","title":"Resolved"}},"type":"object","title":"TrackingSummarySection","description":"Tracking history section (if dog_id provided and has history)."},"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"},"VendorProduct":{"properties":{"sku":{"type":"string","title":"Sku","description":"Vendor's product SKU"},"name":{"type":"string","title":"Name","description":"Vendor's product name"},"price":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Price","description":"Product price"},"currency":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Currency","description":"Price currency (e.g., EUR, USD)"},"url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Url","description":"Product page URL"},"image_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Image Url","description":"Product image URL"}},"type":"object","required":["sku","name"],"title":"VendorProduct","description":"A vendor's product mapped to a Peppula tool key. Only present when the\nvendor has registered their catalogue via POST /v1/sku-mapping."},"VerticalHealthResponse":{"properties":{"request_id":{"type":"string","title":"Request Id"},"vertical":{"type":"string","title":"Vertical","description":"dental, eye, or skin"},"breed":{"type":"string","title":"Breed"},"dog_id":{"type":"string","title":"Dog Id","description":"Dog identifier — yours or auto-generated"},"dog_id_auto_generated":{"type":"boolean","title":"Dog Id Auto Generated","description":"True if we generated the dog_id because none was provided. Use PUT /v1/tracking/dogs to replace with your ID.","default":false},"processing_time_ms":{"type":"integer","title":"Processing Time Ms"},"billable":{"type":"boolean","title":"Billable","description":"Whether this request counts toward your usage quota. False when our analysis failed (Gemini error, timeout). You are never charged for our failures.","default":true},"mc_available":{"type":"boolean","title":"Mc Available","description":"Whether the MobileCLIP classifier contributed to this response. False when MobileCLIP was unavailable (cold start, timeout). The response is still valid — Gemini handles the full analysis — but the dual-opinion cross-check is missing.","default":true},"wellness_indicator":{"anyOf":[{"$ref":"#/components/schemas/WellnessIndicator"},{"type":"null"}]},"overall_assessment":{"type":"string","title":"Overall Assessment","default":""},"photo_quality":{"type":"string","title":"Photo Quality","default":"good"},"conditions":{"items":{"$ref":"#/components/schemas/Condition"},"type":"array","title":"Conditions"},"additional_observations":{"items":{"$ref":"#/components/schemas/AdditionalObservation"},"type":"array","title":"Additional Observations"},"breed_health_flags":{"items":{"type":"string"},"type":"array","title":"Breed Health Flags","description":"Breed health flags relevant to this vertical"},"disclaimer":{"type":"string","title":"Disclaimer","description":"Always shown to the owner on every close-up result","default":"A photo helps us spot what's visible — but some things need a vet's eye. If you notice bleeding, unusual smell, signs of swelling or discharge, or if your dog isn't eating, is lethargic, or isn't behaving normally, don't wait for a photo — show it to your vet."}},"type":"object","required":["request_id","vertical","breed","dog_id","processing_time_ms"],"title":"VerticalHealthResponse","description":"Response from vertical health endpoints."},"WarningSeverity":{"type":"string","enum":["critical","important","informational"],"title":"WarningSeverity"},"WellnessFlag":{"properties":{"flag_id":{"type":"string","title":"Flag Id","description":"Flag identifier (e.g., 'hypothyroid_prone', 'ear_prone')"},"flag_label":{"type":"string","title":"Flag Label"},"relevance":{"type":"string","title":"Relevance","description":"Why this flag matters for THIS dog right now","default":""},"action":{"type":"string","title":"Action","description":"What to do about it","default":""},"action_type":{"$ref":"#/components/schemas/ActionType","default":"informational"},"confidence":{"type":"number","maximum":1.0,"minimum":0.0,"title":"Confidence","default":0.0},"source":{"type":"string","title":"Source","description":"Professional source (e.g., 'Merck Veterinary Manual')","default":""}},"type":"object","required":["flag_id","flag_label"],"title":"WellnessFlag","description":"A breed-specific health predisposition or wellness signal."},"WellnessIndicator":{"properties":{"level":{"type":"string","title":"Level","description":"green, yellow, orange, or red"},"label":{"type":"string","title":"Label","description":"No visible changes, Worth watching, Areas to review, or Worth showing your vet"},"summary":{"type":"string","title":"Summary","description":"One-sentence summary of why this level was assigned","default":""}},"type":"object","required":["level","label"],"title":"WellnessIndicator","description":"Traffic-light wellness indicator based on detected conditions.\nNot a diagnosis — a visual triage of what was observed."},"WellnessReport":{"properties":{"request_id":{"type":"string","title":"Request Id"},"report_type":{"type":"string","title":"Report Type","default":"wellness_assessment"},"generated_at":{"type":"string","title":"Generated At"},"dog_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Dog Id"},"wellness_indicator":{"$ref":"#/components/schemas/WellnessIndicator"},"breed_context":{"$ref":"#/components/schemas/BreedContextSection"},"sections":{"items":{"$ref":"#/components/schemas/ReportSection"},"type":"array","title":"Sections"},"additional_observations":{"items":{"type":"object"},"type":"array","title":"Additional Observations"},"matting_zones":{"items":{"type":"object"},"type":"array","title":"Matting Zones","description":"Breed-specific matting risk zones"},"recommended_tools":{"items":{"type":"object"},"type":"array","title":"Recommended Tools","description":"Tool recommendations with SKU keys"},"style_options":{"items":{"type":"object"},"type":"array","title":"Style Options","description":"Achievable grooming styles"},"safety_warnings":{"items":{"type":"object"},"type":"array","title":"Safety Warnings","description":"Breed/coat safety warnings"},"care_schedule":{"anyOf":[{"type":"object"},{"type":"null"}],"title":"Care Schedule","description":"Brush frequency, groom interval, nail trim, ear check"},"home_care_tips":{"items":{"type":"object"},"type":"array","title":"Home Care Tips","description":"Breed-specific + general home care tips with sources"},"tracking_summary":{"anyOf":[{"$ref":"#/components/schemas/TrackingSummarySection"},{"type":"null"}]},"total_conditions":{"type":"integer","title":"Total Conditions","default":0},"photo_quality":{"anyOf":[{"$ref":"#/components/schemas/PhotoQuality"},{"type":"null"}]}},"type":"object","required":["request_id","generated_at","wellness_indicator","breed_context"],"title":"WellnessReport","description":"A consumer-ready wellness report. Structured sections, ready to embed.\nIncludes everything a groomer needs to attach to a booking or a pet business\nneeds to show a customer — conditions, grooming plan, styles, tools, safety."}}}}