openapi: 3.2.0 info: title: BodySpec Services API description: This API allows BodySpec users to integrate their DEXA scan data with other platforms. license: name: Proprietary version: 0.18.2 servers: - url: https://app.bodyspec.com description: Production server security: - OAuth2: - openid - profile - email - BearerAuth: [] tags: - name: Services description: Available scan types and services paths: /api/v1/services: get: tags: - Services summary: List available services description: Get a list of available scan/test services that can be booked. Currently returns DEXA scans only. operationId: _list_services_api_v1_services_get parameters: - name: page in: query required: false schema: type: integer minimum: 1 description: Page number (starts at 1) default: 1 title: Page description: Page number (starts at 1) - name: page_size in: query required: false schema: type: integer maximum: 100 minimum: 1 description: Items per page (max 100) default: 20 title: Page Size description: Items per page (max 100) responses: '200': description: Successful response content: application/json: schema: $ref: '#/components/schemas/ServicesListResponse' example: services: - name: DEXA description: Dual-energy X-ray Absorptiometry service_id: 8d0e0a1f561f4ec69dbca50ea14336d service_code: DXA duration_minutes: 15 pagination: page: 1 page_size: 20 has_more: false '400': description: Invalid request data content: application/json: example: detail: - loc: - body - phone msg: string does not match regex type: value_error.str.regex '422': description: Validation Error content: application/json: schema: $ref: '#/components/schemas/HTTPValidationError' security: [] /api/v1/services/{service_id}: get: tags: - Services summary: Get service details description: Get detailed information about a specific service. operationId: _get_service_api_v1_services__service_id__get parameters: - name: service_id in: path required: true schema: type: string title: Service Id responses: '200': description: Successful response content: application/json: schema: $ref: '#/components/schemas/ServiceResponse' example: service: name: DEXA description: Dual-energy X-ray Absorptiometry service_id: 8d0e0a1f561f4ec69dbca50ea14336d service_code: DXA duration_minutes: 15 '404': description: Resource not found content: application/json: example: detail: Service not found '422': description: Validation Error content: application/json: schema: $ref: '#/components/schemas/HTTPValidationError' security: [] components: schemas: ServicesListResponse: properties: services: items: $ref: '#/components/schemas/Service' type: array title: Services pagination: $ref: '#/components/schemas/Pagination' type: object required: - services - pagination title: ServicesListResponse description: Response model for listing services. x-internal: true HTTPValidationError: properties: detail: items: $ref: '#/components/schemas/ValidationError' type: array title: Detail type: object title: HTTPValidationError x-internal: true Pagination: properties: page: type: integer title: Page description: Current page number page_size: type: integer title: Page Size description: Number of items per page results: type: integer title: Results description: Number of results in this page has_more: type: boolean title: Has More description: Whether more results exist after this page type: object required: - page - page_size - results - has_more title: Pagination description: Pagination information for list responses. x-internal: true 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 x-internal: true ServiceResponse: properties: service: $ref: '#/components/schemas/Service' type: object required: - service title: ServiceResponse description: Response model for getting a single service. x-internal: true Service: properties: name: type: string title: Name description: Short name of the service (e.g., 'DEXA') description: type: string title: Description description: Full descriptive name of the service service_id: anyOf: - type: string - type: 'null' title: Service Id description: Unique identifier for the service service_code: anyOf: - type: string - type: 'null' title: Service Code description: Service code (e.g., 'DXA', 'RMR', 'VO2') duration_minutes: anyOf: - type: integer - type: 'null' title: Duration Minutes description: Typical duration in minutes last_updated: anyOf: - type: string format: date-time - type: 'null' title: Last Updated description: Last update timestamp in ISO 8601 UTC format type: object required: - name - description title: Service description: Service model representing a bookable scan or test type. securitySchemes: OAuth2: type: oauth2 description: OAuth2 authentication via Keycloak with PKCE flows: authorizationCode: authorizationUrl: https://auth.bodyspec.com/realms/bodyspec/protocol/openid-connect/auth tokenUrl: https://auth.bodyspec.com/realms/bodyspec/protocol/openid-connect/token scopes: openid: OpenID Connect scope profile: Access to user profile email: Access to user email x-usePkce: SHA-256 x-scalar-client-id: bodyspec-api-ext-v1 BearerAuth: type: http scheme: bearer bearerFormat: JWT description: JWT Bearer token for authentication PartnerAuth: type: http scheme: basic description: For partner integrations only. Contact BodySpec to obtain credentials. x-tagGroups: - name: 👤 User Data tags: - Users - Appointments - Results - name: 📅 Availability tags: - Locations - Services - Availability - name: 🤝 Partners tags: - Reservations - Partner Users - Partner Appointments - Partner Results - Partner Intake - Partner Orders - Partner Webhooks - name: 🏥 API Status tags: - API Status