BodySpec Appointments API
Appointments scheduling and management
Appointments scheduling and management
Every API here is available over the APIs.io API and to AI agents over MCP.
One button, every client — Claude, Cursor, VS Code and the rest.
https://apis.io/mcp
find_apisBrowse and filter every API in the catalog.get_api_artifactsOne API's artifacts, grouped by type.get_openapiThe primary OpenAPI for this API.find_similar_apisAPIs that look like this one.apis_io_searchSTART HERE — APIs, providers and tags for one query, each with its total.resolveTurn a domain, URL or GitHub org into the provider it belongs to.find_cohortsEvery scored population of providers in the catalog.curl "https://apis.io/api/v1/apis/bodyspec:bodyspec-appointments-api"
curl "https://apis.io/api/v1/apis?limit=25"
Calls without X-API-Key need no key. Calls with it need a paid plan — get a key.
Free tier, no form to fill in. Signing in shares your email address with us — we store it to create your key and to recognise you if you sign in with another provider. See our Privacy Policy and Terms.
A second provider on the same verified email joins the account you already have.
openapi: 3.2.0
info:
title: BodySpec Appointments 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: Appointments
description: Appointments scheduling and management
paths:
/api/v1/users/me/appts:
get:
tags:
- Appointments
summary: List user appts
description: Retrieve paginated list of appointments for the authenticated user.
operationId: _list_appts_api_v1_users_me_appts_get
security:
- HTTPBearer: []
- OAuth2AuthorizationCodeBearer: []
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)
- name: status
in: query
required: false
schema:
anyOf:
- $ref: '#/components/schemas/ApptStatus'
- type: 'null'
description: 'Filter by appointment outcome: ''scheduled'', ''pending_scan'' (started but results not published yet, or no evidence the location was operating), ''completed'', or ''no_show'''
title: Status
description: 'Filter by appointment outcome: ''scheduled'', ''pending_scan'' (started but results not published yet, or no evidence the location was operating), ''completed'', or ''no_show'''
- name: sort_order
in: query
required: false
schema:
$ref: '#/components/schemas/SortOrder'
description: 'Sort order: ''newest_first'' (latest appointments first) or ''oldest_first'' (earliest appointments first)'
default: newest_first
description: 'Sort order: ''newest_first'' (latest appointments first) or ''oldest_first'' (earliest appointments first)'
- name: start_time[eq]
in: query
required: false
schema:
anyOf:
- type: string
format: date-time
- type: 'null'
description: 'ISO 8601 datetime: start_time = value'
title: Start Time[Eq]
description: 'ISO 8601 datetime: start_time = value'
- name: start_time[gt]
in: query
required: false
schema:
anyOf:
- type: string
format: date-time
- type: 'null'
description: 'ISO 8601 datetime: start_time > value'
title: Start Time[Gt]
description: 'ISO 8601 datetime: start_time > value'
- name: start_time[gte]
in: query
required: false
schema:
anyOf:
- type: string
format: date-time
- type: 'null'
description: 'ISO 8601 datetime: start_time >= value'
title: Start Time[Gte]
description: 'ISO 8601 datetime: start_time >= value'
- name: start_time[lt]
in: query
required: false
schema:
anyOf:
- type: string
format: date-time
- type: 'null'
description: 'ISO 8601 datetime: start_time < value'
title: Start Time[Lt]
description: 'ISO 8601 datetime: start_time < value'
- name: start_time[lte]
in: query
required: false
schema:
anyOf:
- type: string
format: date-time
- type: 'null'
description: 'ISO 8601 datetime: start_time <= value'
title: Start Time[Lte]
description: 'ISO 8601 datetime: start_time <= value'
- name: reserve_time[eq]
in: query
required: false
schema:
anyOf:
- type: string
format: date-time
- type: 'null'
description: 'ISO 8601 datetime: reserve_time = value'
title: Reserve Time[Eq]
description: 'ISO 8601 datetime: reserve_time = value'
- name: reserve_time[gt]
in: query
required: false
schema:
anyOf:
- type: string
format: date-time
- type: 'null'
description: 'ISO 8601 datetime: reserve_time > value'
title: Reserve Time[Gt]
description: 'ISO 8601 datetime: reserve_time > value'
- name: reserve_time[gte]
in: query
required: false
schema:
anyOf:
- type: string
format: date-time
- type: 'null'
description: 'ISO 8601 datetime: reserve_time >= value'
title: Reserve Time[Gte]
description: 'ISO 8601 datetime: reserve_time >= value'
- name: reserve_time[lt]
in: query
required: false
schema:
anyOf:
- type: string
format: date-time
- type: 'null'
description: 'ISO 8601 datetime: reserve_time < value'
title: Reserve Time[Lt]
description: 'ISO 8601 datetime: reserve_time < value'
- name: reserve_time[lte]
in: query
required: false
schema:
anyOf:
- type: string
format: date-time
- type: 'null'
description: 'ISO 8601 datetime: reserve_time <= value'
title: Reserve Time[Lte]
description: 'ISO 8601 datetime: reserve_time <= value'
responses:
'200':
description: Successful response
content:
application/json:
schema:
$ref: '#/components/schemas/ApptListResponse'
example:
appts:
- appt_id: a5950beea2a7487fb79cfdbeb77fa555
start_time: '2024-03-15T10:30:00-07:00'
duration_minutes: 12
location:
location_id: a5950beea2a7487fb79cfdbeb77fa555
name: BodySpec - Culver City
address: 5847 Uplander Way
city_state: Culver City, CA
timezone: US/Pacific
service:
name: DEXA
description: Dual-energy X-ray Absorptiometry scan for body composition
status: completed
reserve_time: '2024-03-01T15:00:00Z'
- appt_id: d7ecde6e9518008607e0e1e3b4b960d9
start_time: '2024-04-20T14:00:00-05:00'
duration_minutes: 12
location:
location_id: d7ecde6e9518008607e0e1e3b4b960d9
name: BodySpec - Dallas
address: 6310 Lemmon Ave Suite 150
city_state: Dallas, TX
timezone: US/Central
service:
name: DEXA
description: Dual-energy X-ray Absorptiometry scan for body composition
status: scheduled
pagination:
page: 1
page_size: 20
has_more: true
'401':
description: Not authenticated
content:
application/json:
example:
detail: Not authenticated
'403':
description: Insufficient permissions
content:
application/json:
example:
detail: Insufficient permissions
'404':
description: User not found
content:
application/json:
example:
detail: User not found
'422':
description: Validation Error
content:
application/json:
schema:
$ref: '#/components/schemas/HTTPValidationError'
/api/v1/users/me/appts/{appt_id}:
get:
tags:
- Appointments
summary: Get appt details
description: Retrieve detailed information for a specific appointment.
operationId: _get_appt_api_v1_users_me_appts__appt_id__get
security:
- HTTPBearer: []
- OAuth2AuthorizationCodeBearer: []
parameters:
- name: appt_id
in: path
required: true
schema:
type: string
title: Appt Id
responses:
'200':
description: Successful response
content:
application/json:
schema:
$ref: '#/components/schemas/Appointment'
example:
appt_id: a5950beea2a7487fb79cfdbeb77fa555
start_time: '2024-03-15T10:30:00-07:00'
duration_minutes: 12
location:
location_id: a5950beea2a7487fb79cfdbeb77fa555
name: BodySpec - Culver City
address: 5847 Uplander Way
city_state: Culver City, CA
timezone: US/Pacific
service:
name: DEXA
description: Dual-energy X-ray Absorptiometry scan for body composition
status: completed
'404':
description: User not found
content:
application/json:
example:
detail: User not found
'401':
description: Not authenticated
content:
application/json:
example:
detail: Not authenticated
'403':
description: Insufficient permissions
content:
application/json:
example:
detail: Insufficient permissions
'422':
description: Validation Error
content:
application/json:
schema:
$ref: '#/components/schemas/HTTPValidationError'
components:
schemas:
Appointment:
properties:
appt_id:
type: string
title: Appt Id
description: Unique identifier for the appointment
start_time:
type: string
format: date-time
title: Start Time
description: Appointment start time in location timezone
duration_minutes:
type: integer
title: Duration Minutes
description: Duration of the appointment in minutes
location:
$ref: '#/components/schemas/Location'
description: Location details
service:
$ref: '#/components/schemas/Service'
description: Service information
status:
$ref: '#/components/schemas/ApptStatus'
description: 'Appointment outcome. `scheduled` — upcoming, results not expected yet. `pending_scan` — the appointment time has passed but results are not published yet, or no other scan at that location later that day produced results either (which reads as a site problem rather than a missed appointment). `completed` — results are published and retrievable. `no_show` — the appointment time has passed with no results, and a later scan at the same location that day did produce results, so the location was operating normally. Note that `pending_scan` can be a lasting state: BodySpec does not record attendance, so an appointment is only reported as `no_show` when there is positive evidence the location was operating. When BodySpec makes the `no_show` determination for a partner appointment, a `reservation_no_show` webhook is emitted.'
reserve_time:
anyOf:
- type: string
format: date-time
- type: 'null'
title: Reserve Time
description: UTC timestamp when the appointment was reserved, if applicable
type: object
required:
- appt_id
- start_time
- duration_minutes
- location
- service
- status
title: Appointment
description: Appointment information.
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
ApptStatus:
type: string
enum:
- scheduled
- pending_scan
- completed
- no_show
title: ApptStatus
description: 'Derived appointment outcome.
BodySpec does not record attendance, so the outcome is inferred from whether
published results exist and from what happened at the same location that day.'
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
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.
Coordinates:
properties:
latitude:
type: number
title: Latitude
description: Latitude in decimal degrees
longitude:
type: number
title: Longitude
description: Longitude in decimal degrees
type: object
required:
- latitude
- longitude
title: Coordinates
description: Geographic coordinates for a location.
x-internal: true
HTTPValidationError:
properties:
detail:
items:
$ref: '#/components/schemas/ValidationError'
type: array
title: Detail
type: object
title: HTTPValidationError
x-internal: true
SortOrder:
type: string
enum:
- newest_first
- oldest_first
title: SortOrder
description: Sort order options for appointment lists.
x-internal: true
ApptListResponse:
properties:
appts:
items:
$ref: '#/components/schemas/Appointment'
type: array
title: Appts
description: List of appointments
pagination:
$ref: '#/components/schemas/Pagination'
description: Pagination information
type: object
required:
- appts
- pagination
title: ApptListResponse
description: Paginated appointment list response.
x-internal: true
Address:
properties:
address_line1:
anyOf:
- type: string
- type: 'null'
title: Address Line1
description: Primary address line
address_line2:
anyOf:
- type: string
- type: 'null'
title: Address Line2
description: Secondary address line (e.g., suite number)
city:
anyOf:
- type: string
- type: 'null'
title: City
description: City name
state:
anyOf:
- type: string
- type: 'null'
title: State
description: State or province
postal_code:
anyOf:
- type: string
- type: 'null'
title: Postal Code
description: Postal/ZIP code
country:
type: string
title: Country
description: Two-letter ISO country code
default: US
type: object
title: Address
description: Address information for a location.
x-internal: true
Location:
properties:
location_id:
type: string
title: Location Id
description: Unique identifier for the location
name:
type: string
title: Name
description: Location name
location_type:
type: string
title: Location Type
description: 'Type of location: ''mobile'' or ''storefront'''
address:
$ref: '#/components/schemas/Address'
description: Address information
coordinates:
anyOf:
- $ref: '#/components/schemas/Coordinates'
- type: 'null'
description: Geographic coordinates
timezone:
anyOf:
- type: string
- type: 'null'
title: Timezone
description: IANA timezone identifier (e.g., 'America/Los_Angeles')
description:
anyOf:
- type: string
- type: 'null'
title: Description
description: Public notes or description
last_updated:
type: string
format: date-time
title: Last Updated
description: Last update timestamp in ISO 8601 UTC format
distance_miles:
anyOf:
- type: number
- type: 'null'
title: Distance Miles
description: Distance from search coordinates in miles. Only present when lat/lng search parameters are provided.
type: object
required:
- location_id
- name
- location_type
- address
- last_updated
title: Location
description: Location model representing a scan location with full details.
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