# BREEDR API Documentation (v0.8.1) Base URL: `/api` All endpoints return JSON responses. Errors follow the format `{ "error": "message" }`. Validation failures return `400`, missing resources return `404`. --- ## 1. Dogs (`/api/dogs`) Manage individual dogs in the kennel. ### `GET /` Get active kennel dogs (paginated). - **Query Params**: - `include_external=1`: Include external dogs (studs/others) - `external_only=1`: Only show external dogs - `page` (default 1), `limit` (default 50, max 200) - `search`: Filter by name or registration number - `sex`: `male` | `female` - **Response**: `{ "data": [Dog...], "total", "page", "limit", "stats": { "total", "males", "females" } }` — each Dog has `sire` and `dam` attached. ### `GET /all` Get all active dogs (kennel + external, unpaginated). Used for dropdowns/pairing/pedigree. ### `GET /:id` Get single dog details. - **Response**: [Dog](#dog-object) object including `sire`, `dam`, and `offspring` array. `404` if not found. ### `POST /` Create a new dog. - **Body**: See [Dog](#dog-object) fields. `name`, `breed`, `sex` are required. - **Validation**: If `sire_id`/`dam_id` are provided they must reference an existing dog of the correct sex (sire → male, dam → female), else `400`. The dog + parent links are written in a single transaction. - **Response**: The created Dog object (`201`). ### `PUT /:id` Update an existing dog. - **Body**: Dog fields to update. - **Validation**: `404` if the dog doesn't exist. Same sire/dam checks as `POST /`, plus a dog cannot be its own parent. - **Response**: The updated Dog object. ### `DELETE /:id` Permanently delete a dog and its related records (health, heat cycles, parent links) in a single transaction. - **Response**: `{ "success": true, "message": "..." }` — `404` if not found. ### `POST /:id/photos` Upload a photo for a dog (JPEG/PNG/GIF/WebP, ≤ 10 MB). - **Form-Data**: `photo` (file) - **Response**: `{ "url": "...", "photos": [...] }` ### `DELETE /:id/photos/:photoIndex` Delete a specific photo from a dog's photo array. - **Validation**: `400` if `photoIndex` is not an integer within the photo array's bounds. - **Response**: `{ "photos": [...] }` --- ## 2. Litters (`/api/litters`) Manage breeding litters and puppy logs. ### `GET /` Get all litters (paginated). - **Query Params**: `page` (default 1), `limit` (default 50) - **Response**: `{ "data": [Litter...], "total", "page", "limit" }` with sire/dam names and puppies attached. ### `GET /:id` Get single litter details. - **Response**: [Litter](#litter-object) object. ### `POST /` Create a new litter. - **Body**: `sire_id`, `dam_id`, `breeding_date` (required), `whelping_date`, `puppy_count`, `notes`. - **Validation**: Sire must be male, dam must be female. - **Response**: The created Litter object. ### `PUT /:id` Update litter details (`breeding_date`, `whelping_date`, `puppy_count`, `notes` — parents cannot change). ### `DELETE /:id` Delete a litter. Puppies are unlinked (their dog records are kept). ### `POST /:id/puppies/:puppyId` Link a dog to a litter as a puppy. - **Side Effect**: Automatically sets the litter's sire and dam as the puppy's parents. ### `DELETE /:id/puppies/:puppyId` Remove a puppy from a litter (sets `litter_id` to NULL). ### `GET /:litterId/puppies/:puppyId/logs` Get weight and health logs for a puppy. ### `POST /:litterId/puppies/:puppyId/logs` Add a weight/health log entry (stored in `health_records`; weights serialized into `description`). - **Body**: `record_date` (required), `weight_oz`, `weight_lbs`, `notes`, `record_type` (default `weight_log`). ### `DELETE /:litterId/puppies/:puppyId/logs/:logId` Delete a weight/health log entry. --- ## 3. Health (`/api/health`) Manage OFA clearances and veterinary records. **Record types** (`record_type`): `ofa_clearance`, `vaccination`, `exam`, `surgery`, `medication`, `other`. **Valid `test_type` values** (OFA clearances only): `hip_ofa`, `hip_pennhip`, `elbow_ofa`, `patella_ofa`, `heart_ofa`, `heart_echo`, `eye_caer`, `thyroid_ofa`. > DNA is **not** a health test type — DNA panels are managed exclusively by the Genetics module (`/api/genetics`). ### `GET /dog/:dogId` Get all health records for a dog. ### `GET /dog/:dogId/clearance-summary` Get GRCA core clearance status (Hip, Elbow, Heart, Eyes). - **Response**: `{ summary, grca_eligible, age_eligible, chic_number }` - Only recurring tests (CAER eyes, advanced/echo cardiac) carry an `expires_at`; permanent certifications (hip, elbow, etc.) never report `expired`/`expiring_soon`. ### `GET /dog/:dogId/chic-eligible` Check if a dog has all required CHIC tests. ### `GET /:id` Get a single health record. ### `POST /` Create health record. - **Body**: `dog_id`, `record_type`, `test_date` (all required), plus optional `test_type`, `test_name`, `ofa_result`, `ofa_number`, `performed_by`, `expires_at`, `result`, `next_due`, `document_url`, `notes`. - **Validation**: `test_type`, if present, must be one of the valid values above (else `400`). - **Note**: `performed_by` is the single clinician field (the legacy `vet_name` column is deprecated). ### `PUT /:id` Update an existing health record. Same body as `POST /` (minus `dog_id`). ### `DELETE /:id` Delete a health record. - **Response**: `{ "message": "Health record deleted successfully" }` ### `POST /upload` Upload a supporting document (PDF or image, ≤ 15 MB) and get back a URL to store in a record's `document_url`. Record-agnostic — works before the record itself is saved. - **Form-Data**: `document` (file) - **Response**: `{ "url": "/uploads/..." }` ### `GET /dog/:dogId/cancer-history` Get cancer-history records for a dog. ### `POST /cancer-history` Add a cancer-history record. - **Body**: `dog_id`, `cancer_type` (required), `age_at_diagnosis`, `age_at_death`, `cause_of_death`, `notes`. --- ## 4. Genetics (`/api/genetics`) Manage DNA panel results and breeding risks. ### `GET /dog/:dogId` Get the full genetic panel for a dog. Returns `tests` (actual records) and `panel` (full list including `not_tested` placeholders). ### `GET /pairing-risk?sireId=X&damId=Y` Check genetic compatibility between two dogs. - **Response**: `{ risks: [...], safe_to_pair: boolean }` ### `GET /:id` Get a single genetic test record. ### `POST /` Add a genetic test result. - **Body**: `dog_id`, `marker`, `result` (clear|carrier|affected|not_tested), plus optional `test_provider`, `test_date`, `document_url`, `notes`. ### `PUT /:id` Update a genetic test result. ### `DELETE /:id` Delete a genetic test result. --- ## 5. Breeding (`/api/breeding`) Track heat cycles and whelping projections. ### `GET /heat-cycles` Get all heat cycles (with dog info). Optional `?year=YYYY&month=M` filter. ### `GET /heat-cycles/active` Get currently active heat cycles. ### `GET /heat-cycles/dog/:dogId` Get all heat cycles for a specific dog. ### `GET /heat-cycles/:id/suggestions` Get optimal breeding window (days 9-15) and whelping projections. ### `POST /heat-cycles` Log a new heat cycle. Dog must be female. - **Body**: `dog_id`, `start_date` (required), `end_date`, `breeding_date`, `breeding_successful`, `notes`. ### `PUT /heat-cycles/:id` Update a heat cycle (same body as `POST`, minus `dog_id`). ### `DELETE /heat-cycles/:id` Delete a heat cycle. ### `GET /whelping-calculator?breeding_date=YYYY-MM-DD` Standalone tool to calculate expected whelping window. --- ## 6. Pedigree (`/api/pedigree`) Advanced ancestry and COI calculations. ### `GET /:id?generations=N` Get an interactive pedigree tree (ancestors). Default 5 generations. ### `GET /:id/descendants?generations=N` Get a descendant tree. Default 3 generations. ### `POST /trial-pairing` Calculate Coefficient of Inbreeding (COI) for a hypothetical mating. (`POST /coi` is an alias.) - **Body**: `sire_id`, `dam_id`. - **Response**: `{ coi, commonAncestors, directRelation, recommendation }` ### `GET /:id/coi` Get the COI for an existing dog (computed from its actual parents). ### `GET /relations/:sireId/:damId` Check the direct relationship between two dogs (parent/offspring, siblings, etc.). ### `GET /:id/cancer-lineage` Cancer history aggregated across a dog's lineage. --- ## 7. Settings (`/api/settings`) ### `GET /` Get kennel metadata (name, address, etc.). ### `PUT /` Update kennel settings. --- ## Data Objects ### Dog Object ```json { "id": 1, "name": "BREEDR Champion", "registration_number": "AKC123456", "breed": "Golden Retriever", "sex": "male", "birth_date": "2020-01-01", "color": "Golden", "microchip": "900123456789", "is_active": 1, "is_champion": 1, "is_external": 0, "photo_urls": ["/uploads/img.jpg"], "notes": "Excellent temperament", "sire": { "id": 10, "name": "Sire Name" }, "dam": { "id": 11, "name": "Dam Name" } } ``` ### Litter Object ```json { "id": 5, "sire_id": 1, "dam_id": 2, "sire_name": "Sire Name", "dam_name": "Dam Name", "breeding_date": "2026-01-01", "whelping_date": "2026-03-05", "puppy_count": 8, "notes": null, "puppies": [ ... ], "actual_puppy_count": 8 } ```