Files
breedr/API.md
T
Jason Stedwell a06ddf0435
Build and Push Docker Image / build (push) Successful in 16s
Docs: bring all documentation current with v0.8.1
- README: v0.8.1 highlights, Node 18+ requirement + client install step for
  manual dev setup, health/genetics features listed, release summary updated
- API.md: paginated response shapes for dogs/litters, validation + status-code
  behavior (400/404), full breeding heat-cycle CRUD, genetics PUT/DELETE,
  pedigree COI/relations/cancer-lineage endpoints, corrected Litter object
- DEVELOPMENT.md: two-layer migration approach documented with schema-drift
  warning, heat_cycles/cancer_history tables, Toast/ConfirmDialog UI patterns
  (no alert/window.confirm), full env-var table, auth-deferred decision noted
- INSTALL.md: fixed API smoke-test (old /api/health root path doesn't exist),
  master -> main
- ROADMAP: v0.8.1 entry; Phase 4b checkboxes reconciled with what's actually
  built; Phase 6 progress; pre-deploy prod-DB check added to QA list

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-06 15:43:23 -05:00

8.9 KiB

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 object including sire, dam, and offspring array. 404 if not found.

POST /

Create a new dog.

  • Body: See Dog 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.

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

{
  "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

{
  "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
}