{
"openapi": "3.1.0",
"info": {
"title": "BuildStability REST API",
"description": "REST API for integrations. Authenticate with OAuth 2.0 Client Credentials. Resources: clients, appointments, programs, revenue, classes, workouts.",
"version": "1.0.0",
"contact": {
"name": "BuildStability Support",
"url": "https://buildstability.com/contact",
"email": "support@buildstability.com"
}
},
"servers": [
{
"url": "https://buildstability.com",
"description": "Production"
},
{
"url": "http://localhost:3000",
"description": "Local"
}
],
"security": [
{
"oauth2": []
}
],
"components": {
"securitySchemes": {
"oauth2": {
"type": "oauth2",
"flows": {
"clientCredentials": {
"tokenUrl": "/api/oauth/token",
"scopes": {
"read": "Read",
"write": "Write"
}
}
}
}
},
"schemas": {
"Client": {
"type": "object",
"properties": {
"id": {
"type": "string",
"format": "uuid",
"description": "Client user ID"
},
"first_name": {
"type": "string",
"maxLength": 100
},
"last_name": {
"type": "string",
"maxLength": 100
},
"email": {
"type": "string",
"format": "email"
},
"phone": {
"type": "string",
"nullable": true,
"maxLength": 20
},
"status": {
"type": "string",
"enum": [
"active",
"archived",
"lead"
]
},
"engagement_score": {
"type": "number",
"nullable": true
},
"last_activity": {
"type": "string",
"format": "date-time",
"nullable": true
},
"created_at": {
"type": "string",
"format": "date-time"
}
}
},
"Appointment": {
"type": "object",
"properties": {
"id": {
"type": "string",
"format": "uuid"
},
"start_time": {
"type": "string",
"format": "date-time"
},
"end_time": {
"type": "string",
"format": "date-time"
},
"status": {
"type": "string"
},
"notes": {
"type": "string",
"nullable": true
},
"is_drop_in": {
"type": "boolean",
"nullable": true
},
"client_id": {
"type": "string",
"format": "uuid",
"nullable": true
},
"client_name": {
"type": "string",
"nullable": true
},
"client_email": {
"type": "string",
"nullable": true
},
"trainer_id": {
"type": "string",
"format": "uuid",
"nullable": true
},
"trainer_name": {
"type": "string",
"nullable": true
},
"class_id": {
"type": "string",
"format": "uuid",
"nullable": true
},
"class_name": {
"type": "string",
"nullable": true
},
"business_id": {
"type": "string",
"format": "uuid"
}
}
},
"Program": {
"type": "object",
"properties": {
"id": {
"type": "string",
"format": "uuid"
},
"status": {
"type": "string"
},
"start_date": {
"type": "string",
"format": "date",
"nullable": true
},
"current_week": {
"type": "number",
"nullable": true
},
"client_id": {
"type": "string",
"format": "uuid",
"nullable": true
},
"client_name": {
"type": "string",
"nullable": true
},
"client_email": {
"type": "string",
"nullable": true
},
"template_name": {
"type": "string",
"nullable": true
},
"template_goal": {
"type": "string",
"nullable": true
},
"business_id": {
"type": "string",
"format": "uuid"
}
}
},
"RevenueSummary": {
"type": "object",
"properties": {
"period": {
"type": "object",
"properties": {
"type": {
"type": "string"
},
"start": {
"type": "string",
"format": "date-time"
},
"end": {
"type": "string",
"format": "date-time"
}
}
},
"sessions": {
"type": "object",
"properties": {
"completed": {
"type": "integer"
}
}
},
"entitlements": {
"type": "object",
"properties": {
"new_subscriptions": {
"type": "integer"
},
"revenue_cents": {
"type": "integer"
},
"revenue_formatted": {
"type": "string"
}
}
},
"summary": {
"type": "object",
"properties": {
"total_revenue_cents": {
"type": "integer"
},
"total_revenue_formatted": {
"type": "string"
},
"note": {
"type": "string"
}
}
}
}
},
"Class": {
"type": "object",
"properties": {
"id": {
"type": "string",
"format": "uuid"
},
"name": {
"type": "string"
},
"business_id": {
"type": "string",
"format": "uuid"
},
"trainer_id": {
"type": "string",
"format": "uuid",
"nullable": true
},
"trainer_name": {
"type": "string",
"nullable": true
},
"duration_minutes": {
"type": "integer",
"nullable": true
},
"capacity": {
"type": "integer",
"nullable": true
},
"schedule_rule": {
"type": "object",
"nullable": true,
"description": "Recurrence rule (days, time)"
},
"is_active": {
"type": "boolean"
},
"created_at": {
"type": "string",
"format": "date-time"
}
}
},
"Workout": {
"type": "object",
"properties": {
"id": {
"type": "integer",
"description": "Workout session ID"
},
"client_id": {
"type": "string",
"format": "uuid"
},
"business_id": {
"type": "string",
"format": "uuid"
},
"assigned_program_id": {
"type": "string",
"format": "uuid",
"nullable": true
},
"status": {
"type": "string"
},
"started_at": {
"type": "string",
"format": "date-time",
"nullable": true
},
"completed_at": {
"type": "string",
"format": "date-time",
"nullable": true
},
"auto_completed_at": {
"type": "string",
"format": "date-time",
"nullable": true
},
"workout_date": {
"type": "string",
"format": "date",
"nullable": true
},
"trainer_notes": {
"type": "string",
"nullable": true
},
"program_name": {
"type": "string",
"nullable": true
}
}
},
"Error": {
"type": "object",
"properties": {
"error": {
"type": "string",
"example": "invalid_request"
},
"error_description": {
"type": "string"
},
"details": {
"type": "array",
"items": {
"type": "object",
"properties": {
"field": {
"type": "string"
},
"message": {
"type": "string"
}
}
}
}
}
},
"OAuthTokenRequest": {
"type": "object",
"required": [
"grant_type",
"client_id",
"client_secret"
],
"properties": {
"grant_type": {
"type": "string",
"enum": [
"client_credentials"
]
},
"client_id": {
"type": "string"
},
"client_secret": {
"type": "string"
},
"scope": {
"type": "string",
"description": "Optional space-separated scopes to request"
}
}
},
"CreateClientRequest": {
"type": "object",
"required": [
"first_name",
"last_name",
"email"
],
"properties": {
"first_name": {
"type": "string",
"minLength": 1,
"maxLength": 100
},
"last_name": {
"type": "string",
"minLength": 1,
"maxLength": 100
},
"email": {
"type": "string",
"format": "email"
},
"phone": {
"type": "string",
"maxLength": 20,
"nullable": true
}
}
},
"UpdateClientRequest": {
"type": "object",
"properties": {
"first_name": {
"type": "string",
"minLength": 1,
"maxLength": 100
},
"last_name": {
"type": "string",
"minLength": 1,
"maxLength": 100
},
"email": {
"type": "string",
"format": "email"
},
"phone": {
"type": "string",
"maxLength": 20,
"nullable": true
},
"status": {
"type": "string",
"enum": [
"active",
"archived",
"lead"
]
}
}
}
}
},
"paths": {
"/api/oauth/token": {
"post": {
"summary": "Get access token",
"description": "OAuth 2.0 Client Credentials. Send as application/x-www-form-urlencoded.",
"tags": [
"OAuth"
],
"security": [],
"requestBody": {
"content": {
"application/x-www-form-urlencoded": {
"schema": {
"$ref": "#/components/schemas/OAuthTokenRequest"
}
}
}
},
"responses": {
"200": {
"description": "Token",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"access_token": {
"type": "string"
},
"token_type": {
"type": "string",
"example": "Bearer"
},
"expires_in": {
"type": "integer"
},
"scope": {
"type": "string"
}
}
}
}
}
},
"400": {
"description": "Invalid request",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"401": {
"description": "Invalid credentials",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
}
},
"/api/v1/health": {
"get": {
"summary": "Health",
"tags": [
"Health"
],
"security": [],
"responses": {
"200": {
"description": "OK",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"status": {
"type": "string",
"example": "ok"
},
"version": {
"type": "string",
"example": "v1"
}
}
}
}
}
}
}
},
"/api/v1/clients": {
"get": {
"summary": "List clients",
"tags": [
"Clients"
],
"parameters": [
{
"name": "status",
"in": "query",
"schema": {
"type": "string",
"enum": [
"active",
"archived",
"lead",
"all"
]
},
"description": "Default: active"
},
{
"name": "search",
"in": "query",
"schema": {
"type": "string"
},
"description": "Search by name or email"
},
{
"name": "limit",
"in": "query",
"schema": {
"type": "integer",
"default": 50,
"maximum": 100
}
},
{
"name": "offset",
"in": "query",
"schema": {
"type": "integer",
"default": 0
}
}
],
"responses": {
"200": {
"description": "List",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"data": {
"type": "array",
"items": {
"$ref": "#/components/schemas/Client"
}
},
"pagination": {
"type": "object",
"properties": {
"total": {
"type": "integer"
},
"limit": {
"type": "integer"
},
"offset": {
"type": "integer"
},
"has_more": {
"type": "boolean"
}
}
}
}
}
}
}
},
"401": {
"description": "Unauthorized"
},
"429": {
"description": "Rate limited"
}
}
},
"post": {
"summary": "Create client",
"tags": [
"Clients"
],
"requestBody": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/CreateClientRequest"
}
}
}
},
"responses": {
"201": {
"description": "Created",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"data": {
"$ref": "#/components/schemas/Client"
}
}
}
}
}
},
"400": {
"description": "Validation failed",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"401": {
"description": "Unauthorized"
}
}
}
},
"/api/v1/clients/{id}": {
"get": {
"summary": "Get client",
"tags": [
"Clients"
],
"parameters": [
{
"name": "id",
"in": "path",
"required": true,
"schema": {
"type": "string",
"format": "uuid"
}
}
],
"responses": {
"200": {
"description": "OK",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"data": {
"$ref": "#/components/schemas/Client"
}
}
}
}
}
},
"404": {
"description": "Not found"
}
},
"put": {
"summary": "Update client",
"tags": [
"Clients"
],
"parameters": [
{
"name": "id",
"in": "path",
"required": true,
"schema": {
"type": "string",
"format": "uuid"
}
}
],
"requestBody": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/UpdateClientRequest"
}
}
}
},
"responses": {
"200": {
"400": {
"description": "Validation failed"
},
"404": {
"description": "Not found"
},
"description": "OK",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"data": {
"$ref": "#/components/schemas/Client"
}
}
}
}
}
}
},
"delete": {
"summary": "Archive client",
"tags": [
"Clients"
],
"parameters": [
{
"name": "id",
"in": "path",
"required": true,
"schema": {
"type": "string",
"format": "uuid"
}
}
],
"responses": {
"204": {
"description": "No content"
},
"404": {
"description": "Not found"
}
}
}
},
"/api/v1/appointments": {
"get": {
"summary": "List appointments",
"tags": [
"Appointments"
],
"parameters": [
{
"name": "start_date",
"in": "query",
"schema": {
"type": "string",
"format": "date"
}
},
{
"name": "end_date",
"in": "query",
"schema": {
"type": "string",
"format": "date"
}
},
{
"name": "trainer_id",
"in": "query",
"schema": {
"type": "string",
"format": "uuid"
}
},
{
"name": "status",
"in": "query",
"schema": {
"type": "string"
}
},
{
"name": "limit",
"in": "query",
"schema": {
"type": "integer",
"default": 50,
"maximum": 100
}
},
{
"name": "offset",
"in": "query",
"schema": {
"type": "integer",
"default": 0
}
}
],
"responses": {
"200": {
"description": "List",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"data": {
"type": "array",
"items": {
"$ref": "#/components/schemas/Appointment"
}
},
"pagination": {
"type": "object"
}
}
}
}
}
},
"401": {},
"429": {}
}
}
},
"/api/v1/appointments/{id}": {
"get": {
"summary": "Get appointment",
"tags": [
"Appointments"
],
"parameters": [
{
"name": "id",
"in": "path",
"required": true,
"schema": {
"type": "string",
"format": "uuid"
}
}
],
"responses": {
"200": {
"description": "OK",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"data": {
"$ref": "#/components/schemas/Appointment"
}
}
}
}
}
},
"404": {}
}
}
},
"/api/v1/programs": {
"get": {
"summary": "List programs",
"tags": [
"Programs"
],
"parameters": [
{
"name": "status",
"in": "query",
"schema": {
"type": "string"
}
},
{
"name": "client_id",
"in": "query",
"schema": {
"type": "string",
"format": "uuid"
}
},
{
"name": "limit",
"in": "query",
"schema": {
"type": "integer",
"default": 50,
"maximum": 100
}
},
{
"name": "offset",
"in": "query",
"schema": {
"type": "integer",
"default": 0
}
}
],
"responses": {
"200": {
"description": "List",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"data": {
"type": "array",
"items": {
"$ref": "#/components/schemas/Program"
}
},
"pagination": {
"type": "object"
}
}
}
}
}
},
"401": {},
"429": {}
}
}
},
"/api/v1/programs/{id}": {
"get": {
"summary": "Get program",
"tags": [
"Programs"
],
"parameters": [
{
"name": "id",
"in": "path",
"required": true,
"schema": {
"type": "string",
"format": "uuid"
}
}
],
"responses": {
"200": {
"description": "OK",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"data": {
"$ref": "#/components/schemas/Program"
}
}
}
}
}
},
"404": {}
}
}
},
"/api/v1/revenue": {
"get": {
"summary": "Revenue summary",
"tags": [
"Revenue"
],
"parameters": [
{
"name": "period",
"in": "query",
"schema": {
"type": "string",
"enum": [
"today",
"week",
"month",
"year",
"custom"
]
},
"description": "Default: month. For custom, start_date and end_date required."
},
{
"name": "start_date",
"in": "query",
"schema": {
"type": "string",
"format": "date"
}
},
{
"name": "end_date",
"in": "query",
"schema": {
"type": "string",
"format": "date"
}
}
],
"responses": {
"200": {
"description": "OK",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"data": {
"$ref": "#/components/schemas/RevenueSummary"
}
}
}
}
}
},
"400": {
"description": "Invalid period or missing dates for custom"
},
"401": {}
}
}
}
},
"/api/v1/classes": {
"get": {
"summary": "List classes",
"tags": [
"Classes"
],
"parameters": [
{
"name": "is_active",
"in": "query",
"schema": {
"type": "boolean"
},
"description": "Filter by active status"
},
{
"name": "trainer_id",
"in": "query",
"schema": {
"type": "string",
"format": "uuid"
}
},
{
"name": "limit",
"in": "query",
"schema": {
"type": "integer",
"default": 50,
"maximum": 100
}
},
{
"name": "offset",
"in": "query",
"schema": {
"type": "integer",
"default": 0
}
}
],
"responses": {
"200": {
"description": "List",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"data": {
"type": "array",
"items": {
"$ref": "#/components/schemas/Class"
}
},
"pagination": {
"type": "object",
"properties": {
"total": {
"type": "integer"
},
"limit": {},
"offset": {},
"has_more": {}
}
}
}
}
}
}
},
"401": {},
"429": {}
}
}
}
},
"/api/v1/classes/{id}": {
"get": {
"summary": "Get class",
"tags": [
"Classes"
],
"parameters": [
{
"name": "id",
"in": "path",
"required": true,
"schema": {
"type": "string",
"format": "uuid"
}
}
],
"responses": {
"200": {
"description": "OK",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"data": {
"$ref": "#/components/schemas/Class"
}
}
}
}
}
},
"404": {}
}
}
},
"/api/v1/workouts": {
"get": {
"summary": "List workout sessions",
"tags": [
"Workouts"
],
"parameters": [
{
"name": "client_id",
"in": "query",
"schema": {
"type": "string",
"format": "uuid"
}
},
{
"name": "status",
"in": "query",
"schema": {
"type": "string"
}
},
{
"name": "limit",
"in": "query",
"schema": {
"type": "integer",
"default": 50,
"maximum": 100
}
},
{
"name": "offset",
"in": "query",
"schema": {
"type": "integer",
"default": 0
}
}
],
"responses": {
"200": {
"description": "List",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"data": {
"type": "array",
"items": {
"$ref": "#/components/schemas/Workout"
}
},
"pagination": {
"type": "object"
}
}
}
}
}
},
"401": {},
"429": {}
}
}
}
},
"/api/v1/workouts/{id}": {
"get": {
"summary": "Get workout session",
"tags": [
"Workouts"
],
"parameters": [
{
"name": "id",
"in": "path",
"required": true,
"schema": {
"type": "integer"
},
"description": "Workout session ID (numeric)"
}
],
"responses": {
"200": {
"description": "OK",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"data": {
"$ref": "#/components/schemas/Workout"
}
}
}
}
}
},
"400": {
"description": "Invalid id"
},
"404": {}
}
}
}
}
}