Files
openapi-first/openapi_first/templates/vet_app/openapi.yaml

1081 lines
29 KiB
YAML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

openapi: 3.1.0
info:
title: Veterinary Clinic API
version: 1.0.0
description: |
Veterinary clinic management API demonstrating OpenAPI x- extension
fields for the react-openapi admin panel renderer.
servers:
- url: http://localhost:8000
components:
schemas:
Metadata:
type: object
x-display-format: "created:{createdOn}|updated:{updatedOn}"
properties:
createdOn:
type: string
format: date-time
updatedOn:
type: string
format: date-time
Procedure:
type: object
x-display-format: "{name} — ${cost}"
properties:
name:
type: string
x-order: 1
x-label: "Procedure Name"
description:
type: string
x-order: 2
x-label: "Description"
cost:
type: number
format: float
x-order: 3
x-label: "Cost"
notes:
$ref: '#/components/schemas/ProcedureNotes'
x-order: 4
x-label: "Notes"
ProcedureNotes:
type: object
x-display-format: "{summary}"
properties:
summary:
type: string
x-order: 1
x-label: "Summary"
details:
type: string
x-order: 2
x-label: "Details"
Parent:
type: object
x-resource: parents
x-primary-key: id
x-display-format: "{name}"
x-list-columns: [name, email, phone]
properties:
id:
type: integer
readOnly: true
x-order: 0
x-hidden: { form: true, list: true }
x-label: "ID"
name:
type: string
x-order: 1
x-label: "Name"
x-description: "Parent's full name"
x-filterable: true
x-sortable: true
email:
type: string
format: email
x-order: 2
x-label: "Email"
x-description: "Email address"
x-filterable: true
phone:
type: string
x-order: 3
x-label: "Phone"
x-description: "Contact phone number"
x-filterable: true
metadata:
$ref: '#/components/schemas/Metadata'
x-order: 4
x-label: "Metadata"
required: [id, name, email]
Vet:
type: object
x-resource: vets
x-primary-key: id
x-display-format: "Dr. {name}"
x-list-columns: [name, specialty, email, phone]
properties:
id:
type: integer
readOnly: true
x-order: 0
x-hidden: { form: true, list: true }
x-label: "ID"
name:
type: string
x-order: 1
x-label: "Name"
x-description: "Veterinarian's full name"
x-filterable: true
x-sortable: true
specialty:
type: string
x-order: 2
x-label: "Specialty"
x-description: "Area of specialization"
x-filterable: true
email:
type: string
format: email
x-order: 3
x-label: "Email"
x-description: "Email address"
x-filterable: true
phone:
type: string
x-order: 4
x-label: "Phone"
x-description: "Contact phone number"
metadata:
$ref: '#/components/schemas/Metadata'
x-order: 4
x-label: "Metadata"
required: [id, name]
Treatment:
type: object
x-resource: treatments
x-primary-key: id
x-display-format: "{label}"
x-list-columns: [label, description]
properties:
id:
type: integer
readOnly: true
x-order: 0
x-hidden: { form: true, list: true }
x-label: "ID"
label:
type: string
x-order: 1
x-label: "Treatment"
x-description: "Name of the treatment"
x-filterable: true
x-sortable: true
description:
type: string
x-order: 2
x-label: "Description"
x-description: "Detailed description of the treatment"
metadata:
$ref: '#/components/schemas/Metadata'
x-order: 4
x-label: "Metadata"
required: [id, label]
Pet:
type: object
x-resource: pets
x-primary-key: id
x-display-format: "{name} #{id}"
x-list-columns: [name, species, age, weight, birthDate, parents]
properties:
id:
type: integer
readOnly: true
x-order: 0
x-hidden: { form: true, list: true }
x-label: "ID"
name:
type: string
x-order: 1
x-label: "Pet Name"
x-description: "Name of the pet"
x-filterable: true
x-sortable: true
species:
type: string
enum: [dog, cat, bird]
x-order: 2
x-label: "Species"
x-description: "Type of animal"
x-filterable: true
age:
type: integer
x-order: 3
x-label: "Age"
x-description: "Age in years"
x-filterable: true
x-sortable: true
weight:
type: number
format: float
x-order: 4
x-label: "Weight"
x-description: "Weight in kilograms"
birthDate:
type: string
format: date
x-order: 5
x-label: "Date of Birth"
x-description: "Pet's birth date"
x-filterable: true
photo:
type: string
format: binary
x-ui-type: image
x-upload-url: /pets/{id}/photo
x-order: 6
x-label: "Photo"
x-description: "Upload a photo of the pet"
parents:
type: array
items:
$ref: '#/components/schemas/Parent'
x-fk:
resource: parents
x-order: 7
x-label: "Parents"
x-description: "Pet's owners"
x-filterable: true
metadata:
$ref: '#/components/schemas/Metadata'
x-order: 4
x-label: "Metadata"
required: [id, name, parents]
Appointment:
type: object
x-resource: appointments
x-primary-key: id
x-display-format: "Appt #{id} {date}"
x-list-columns: [date, pet, vet, treatment, notes]
properties:
id:
type: integer
readOnly: true
x-order: 0
x-hidden: { form: true, list: true }
x-label: "ID"
date:
type: string
format: date-time
x-order: 1
x-label: "Date & Time"
x-description: "Appointment date and time"
x-filterable: true
x-sortable: true
notes:
type: string
x-order: 2
x-label: "Notes"
x-description: "Any additional notes"
procedures:
type: array
items:
$ref: '#/components/schemas/Procedure'
x-order: 3
x-label: "Procedures"
x-description: "List of procedures performed during this appointment"
pet:
$ref: '#/components/schemas/Pet'
x-fk:
resource: pets
x-order: 3
x-label: "Pet"
x-description: "Select a pet"
x-filterable: true
vet:
$ref: '#/components/schemas/Vet'
x-fk:
resource: vets
prefetch: true
x-order: 4
x-label: "Veterinarian"
x-description: "Select a veterinarian"
x-filterable: true
treatment:
$ref: '#/components/schemas/Treatment'
x-fk:
resource: treatments
prefetch: true
x-order: 5
x-label: "Treatment"
x-description: "Select a treatment"
x-filterable: true
metadata:
$ref: '#/components/schemas/Metadata'
x-order: 4
x-label: "Metadata"
required: [id, date, pet, vet, treatment]
ErrorBody:
type: object
properties:
detail:
type: string
required: [detail]
HTTPValidationError:
type: object
properties:
detail:
type: array
items:
$ref: '#/components/schemas/ValidationError'
ValidationError:
type: object
properties:
loc:
type: array
items:
type: string
msg:
type: string
type:
type: string
required: [loc, msg, type]
responses:
Unauthorized:
description: Not authenticated
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorBody'
Forbidden:
description: Insufficient permissions
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorBody'
NotFound:
description: Resource not found
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorBody'
ValidationError:
description: Validation Error
content:
application/json:
schema:
$ref: '#/components/schemas/HTTPValidationError'
InternalServerError:
description: Internal server error
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorBody'
paths:
/parents:
get:
summary: List parents (paginated)
operationId: list_parents
parameters:
- in: query
name: limit
schema: {type: integer, default: 20}
- in: query
name: offset
schema: {type: integer, default: 0}
responses:
'200':
description: Paginated list of parents
content:
application/json:
schema:
type: object
properties:
total:
type: integer
items:
type: array
items:
$ref: '#/components/schemas/Parent'
'401':
$ref: '#/components/responses/Unauthorized'
'403':
$ref: '#/components/responses/Forbidden'
'422':
$ref: '#/components/responses/ValidationError'
'500':
$ref: '#/components/responses/InternalServerError'
post:
summary: Create a parent
operationId: create_parent
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/Parent'
responses:
'201':
description: Parent created
content:
application/json:
schema:
$ref: '#/components/schemas/Parent'
'401':
$ref: '#/components/responses/Unauthorized'
'403':
$ref: '#/components/responses/Forbidden'
'422':
$ref: '#/components/responses/ValidationError'
'500':
$ref: '#/components/responses/InternalServerError'
/parents/{id}:
get:
operationId: get_parent
parameters:
- name: id
in: path
required: true
schema: {type: integer}
responses:
'200':
description: Single parent
content:
application/json:
schema:
$ref: '#/components/schemas/Parent'
'401':
$ref: '#/components/responses/Unauthorized'
'403':
$ref: '#/components/responses/Forbidden'
'404':
$ref: '#/components/responses/NotFound'
'422':
$ref: '#/components/responses/ValidationError'
'500':
$ref: '#/components/responses/InternalServerError'
put:
operationId: update_parent
parameters:
- name: id
in: path
required: true
schema: {type: integer}
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/Parent'
responses:
'200':
description: Parent updated
content:
application/json:
schema:
$ref: '#/components/schemas/Parent'
'401':
$ref: '#/components/responses/Unauthorized'
'403':
$ref: '#/components/responses/Forbidden'
'404':
$ref: '#/components/responses/NotFound'
'422':
$ref: '#/components/responses/ValidationError'
'500':
$ref: '#/components/responses/InternalServerError'
delete:
operationId: delete_parent
parameters:
- name: id
in: path
required: true
schema: {type: integer}
responses:
'204':
description: Parent deleted
'401':
$ref: '#/components/responses/Unauthorized'
'403':
$ref: '#/components/responses/Forbidden'
'404':
$ref: '#/components/responses/NotFound'
'422':
$ref: '#/components/responses/ValidationError'
'500':
$ref: '#/components/responses/InternalServerError'
/vets:
get:
summary: List vets (paginated)
operationId: list_vets
parameters:
- in: query
name: limit
schema: {type: integer, default: 20}
- in: query
name: offset
schema: {type: integer, default: 0}
responses:
'200':
description: Paginated list of vets
content:
application/json:
schema:
type: object
properties:
total:
type: integer
items:
type: array
items:
$ref: '#/components/schemas/Vet'
'401':
$ref: '#/components/responses/Unauthorized'
'403':
$ref: '#/components/responses/Forbidden'
'422':
$ref: '#/components/responses/ValidationError'
'500':
$ref: '#/components/responses/InternalServerError'
post:
summary: Create a vet
operationId: create_vet
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/Vet'
responses:
'201':
description: Vet created
content:
application/json:
schema:
$ref: '#/components/schemas/Vet'
'401':
$ref: '#/components/responses/Unauthorized'
'403':
$ref: '#/components/responses/Forbidden'
'422':
$ref: '#/components/responses/ValidationError'
'500':
$ref: '#/components/responses/InternalServerError'
/vets/{id}:
get:
operationId: get_vet
parameters:
- name: id
in: path
required: true
schema: {type: integer}
responses:
'200':
description: Single vet
content:
application/json:
schema:
$ref: '#/components/schemas/Vet'
'401':
$ref: '#/components/responses/Unauthorized'
'403':
$ref: '#/components/responses/Forbidden'
'404':
$ref: '#/components/responses/NotFound'
'422':
$ref: '#/components/responses/ValidationError'
'500':
$ref: '#/components/responses/InternalServerError'
put:
operationId: update_vet
parameters:
- name: id
in: path
required: true
schema: {type: integer}
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/Vet'
responses:
'200':
description: Vet updated
content:
application/json:
schema:
$ref: '#/components/schemas/Vet'
'401':
$ref: '#/components/responses/Unauthorized'
'403':
$ref: '#/components/responses/Forbidden'
'404':
$ref: '#/components/responses/NotFound'
'422':
$ref: '#/components/responses/ValidationError'
'500':
$ref: '#/components/responses/InternalServerError'
delete:
operationId: delete_vet
parameters:
- name: id
in: path
required: true
schema: {type: integer}
responses:
'204':
description: Vet deleted
'401':
$ref: '#/components/responses/Unauthorized'
'403':
$ref: '#/components/responses/Forbidden'
'404':
$ref: '#/components/responses/NotFound'
'422':
$ref: '#/components/responses/ValidationError'
'500':
$ref: '#/components/responses/InternalServerError'
/treatments:
get:
summary: List treatments (catalogue)
operationId: list_treatments
responses:
'200':
description: List of treatments
content:
application/json:
schema:
type: array
items:
$ref: '#/components/schemas/Treatment'
'401':
$ref: '#/components/responses/Unauthorized'
'403':
$ref: '#/components/responses/Forbidden'
'422':
$ref: '#/components/responses/ValidationError'
'500':
$ref: '#/components/responses/InternalServerError'
post:
summary: Add a treatment (admin only)
operationId: create_treatment
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/Treatment'
responses:
'201':
description: Treatment added
content:
application/json:
schema:
$ref: '#/components/schemas/Treatment'
'401':
$ref: '#/components/responses/Unauthorized'
'403':
$ref: '#/components/responses/Forbidden'
'422':
$ref: '#/components/responses/ValidationError'
'500':
$ref: '#/components/responses/InternalServerError'
/treatments/{id}:
get:
operationId: get_treatment
parameters:
- name: id
in: path
required: true
schema: {type: integer}
responses:
'200':
description: Single treatment
content:
application/json:
schema:
$ref: '#/components/schemas/Treatment'
'401':
$ref: '#/components/responses/Unauthorized'
'403':
$ref: '#/components/responses/Forbidden'
'404':
$ref: '#/components/responses/NotFound'
'422':
$ref: '#/components/responses/ValidationError'
'500':
$ref: '#/components/responses/InternalServerError'
put:
operationId: update_treatment
parameters:
- name: id
in: path
required: true
schema: {type: integer}
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/Treatment'
responses:
'200':
description: Treatment updated
content:
application/json:
schema:
$ref: '#/components/schemas/Treatment'
'401':
$ref: '#/components/responses/Unauthorized'
'403':
$ref: '#/components/responses/Forbidden'
'404':
$ref: '#/components/responses/NotFound'
'422':
$ref: '#/components/responses/ValidationError'
'500':
$ref: '#/components/responses/InternalServerError'
delete:
operationId: delete_treatment
parameters:
- name: id
in: path
required: true
schema: {type: integer}
responses:
'204':
description: Treatment deleted
'401':
$ref: '#/components/responses/Unauthorized'
'403':
$ref: '#/components/responses/Forbidden'
'404':
$ref: '#/components/responses/NotFound'
'422':
$ref: '#/components/responses/ValidationError'
'500':
$ref: '#/components/responses/InternalServerError'
/pets:
get:
summary: List pets (paginated)
operationId: list_pets
parameters:
- in: query
name: limit
schema: {type: integer, default: 20}
- in: query
name: offset
schema: {type: integer, default: 0}
responses:
'200':
description: Paginated list of pets
content:
application/json:
schema:
type: object
properties:
total:
type: integer
items:
type: array
items:
$ref: '#/components/schemas/Pet'
'401':
$ref: '#/components/responses/Unauthorized'
'403':
$ref: '#/components/responses/Forbidden'
'422':
$ref: '#/components/responses/ValidationError'
'500':
$ref: '#/components/responses/InternalServerError'
post:
summary: Create a pet
operationId: create_pet
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/Pet'
responses:
'201':
description: Pet created
content:
application/json:
schema:
$ref: '#/components/schemas/Pet'
'401':
$ref: '#/components/responses/Unauthorized'
'403':
$ref: '#/components/responses/Forbidden'
'422':
$ref: '#/components/responses/ValidationError'
'500':
$ref: '#/components/responses/InternalServerError'
/pets/{id}:
get:
operationId: get_pet
parameters:
- name: id
in: path
required: true
schema: {type: integer}
responses:
'200':
description: Single pet
content:
application/json:
schema:
$ref: '#/components/schemas/Pet'
'401':
$ref: '#/components/responses/Unauthorized'
'403':
$ref: '#/components/responses/Forbidden'
'404':
$ref: '#/components/responses/NotFound'
'422':
$ref: '#/components/responses/ValidationError'
'500':
$ref: '#/components/responses/InternalServerError'
put:
operationId: update_pet
parameters:
- name: id
in: path
required: true
schema: {type: integer}
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/Pet'
responses:
'200':
description: Pet updated
content:
application/json:
schema:
$ref: '#/components/schemas/Pet'
'401':
$ref: '#/components/responses/Unauthorized'
'403':
$ref: '#/components/responses/Forbidden'
'404':
$ref: '#/components/responses/NotFound'
'422':
$ref: '#/components/responses/ValidationError'
'500':
$ref: '#/components/responses/InternalServerError'
delete:
operationId: delete_pet
parameters:
- name: id
in: path
required: true
schema: {type: integer}
responses:
'204':
description: Pet deleted
'401':
$ref: '#/components/responses/Unauthorized'
'403':
$ref: '#/components/responses/Forbidden'
'404':
$ref: '#/components/responses/NotFound'
'422':
$ref: '#/components/responses/ValidationError'
'500':
$ref: '#/components/responses/InternalServerError'
post:
summary: Upload pet photo
operationId: upload_pet_photo
parameters:
- name: id
in: path
required: true
schema: {type: integer}
requestBody:
required: true
content:
multipart/form-data:
schema:
type: object
properties:
file:
type: string
format: binary
responses:
'200':
description: Photo uploaded
'401':
$ref: '#/components/responses/Unauthorized'
'403':
$ref: '#/components/responses/Forbidden'
'422':
$ref: '#/components/responses/ValidationError'
'500':
$ref: '#/components/responses/InternalServerError'
/appointments:
get:
summary: List appointments (paginated, filterable)
operationId: list_appointments
parameters:
- in: query
name: limit
schema: {type: integer, default: 20}
- in: query
name: offset
schema: {type: integer, default: 0}
- in: query
name: date
schema: {type: string, format: date}
- in: query
name: vet
schema: {type: integer}
- in: query
name: pet
schema: {type: integer}
responses:
'200':
description: Paginated list of appointments
content:
application/json:
schema:
type: object
properties:
total:
type: integer
items:
type: array
items:
$ref: '#/components/schemas/Appointment'
'401':
$ref: '#/components/responses/Unauthorized'
'403':
$ref: '#/components/responses/Forbidden'
'422':
$ref: '#/components/responses/ValidationError'
'500':
$ref: '#/components/responses/InternalServerError'
post:
summary: Create an appointment
operationId: create_appointment
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/Appointment'
responses:
'201':
description: Appointment created
content:
application/json:
schema:
$ref: '#/components/schemas/Appointment'
'401':
$ref: '#/components/responses/Unauthorized'
'403':
$ref: '#/components/responses/Forbidden'
'422':
$ref: '#/components/responses/ValidationError'
'500':
$ref: '#/components/responses/InternalServerError'
/calls:
get:
summary: Stream random animal sounds via SSE
operationId: stream_calls
x-sse: true
responses:
'200':
description: SSE stream of random animal sounds
content:
text/event-stream:
schema:
type: object
required: [sound]
properties:
sound:
type: string
enum: [woof, meow, coo]
description: Random animal sound
/appointments/{id}:
get:
operationId: get_appointment
parameters:
- name: id
in: path
required: true
schema: {type: integer}
responses:
'200':
description: Single appointment
content:
application/json:
schema:
$ref: '#/components/schemas/Appointment'
'401':
$ref: '#/components/responses/Unauthorized'
'403':
$ref: '#/components/responses/Forbidden'
'404':
$ref: '#/components/responses/NotFound'
'422':
$ref: '#/components/responses/ValidationError'
'500':
$ref: '#/components/responses/InternalServerError'
put:
operationId: update_appointment
parameters:
- name: id
in: path
required: true
schema: {type: integer}
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/Appointment'
responses:
'200':
description: Appointment updated
content:
application/json:
schema:
$ref: '#/components/schemas/Appointment'
'401':
$ref: '#/components/responses/Unauthorized'
'403':
$ref: '#/components/responses/Forbidden'
'404':
$ref: '#/components/responses/NotFound'
'422':
$ref: '#/components/responses/ValidationError'
'500':
$ref: '#/components/responses/InternalServerError'
delete:
operationId: delete_appointment
parameters:
- name: id
in: path
required: true
schema: {type: integer}
responses:
'204':
description: Appointment deleted
'401':
$ref: '#/components/responses/Unauthorized'
'403':
$ref: '#/components/responses/Forbidden'
'404':
$ref: '#/components/responses/NotFound'
'422':
$ref: '#/components/responses/ValidationError'
'500':
$ref: '#/components/responses/InternalServerError'