mirror of
https://github.com/Dvorinka/Bookra.git
synced 2026-06-04 04:22:59 +00:00
first commit
This commit is contained in:
@@ -0,0 +1,498 @@
|
||||
openapi: 3.0.3
|
||||
info:
|
||||
title: Bookra API
|
||||
version: 0.1.0
|
||||
description: >
|
||||
Remote-first booking API for Bookra. The Go backend owns business rules,
|
||||
scheduling logic, tenant isolation, and Stripe-backed plan enforcement.
|
||||
servers:
|
||||
- url: http://localhost:8080
|
||||
tags:
|
||||
- name: Health
|
||||
- name: Public Booking
|
||||
- name: Dashboard
|
||||
- name: Tenant
|
||||
- name: Billing
|
||||
- name: Jobs
|
||||
paths:
|
||||
/healthz:
|
||||
get:
|
||||
tags: [Health]
|
||||
operationId: getHealth
|
||||
responses:
|
||||
"200":
|
||||
description: Service health
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/HealthResponse"
|
||||
/v1/meta/config:
|
||||
get:
|
||||
tags: [Health]
|
||||
operationId: getPublicConfig
|
||||
responses:
|
||||
"200":
|
||||
description: Public runtime configuration
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/PublicConfig"
|
||||
/v1/public/tenants/{tenantSlug}/availability:
|
||||
get:
|
||||
tags: [Public Booking]
|
||||
operationId: getPublicAvailability
|
||||
parameters:
|
||||
- in: path
|
||||
name: tenantSlug
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
responses:
|
||||
"200":
|
||||
description: Availability for a tenant booking page
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/PublicAvailabilityResponse"
|
||||
/v1/public/bookings:
|
||||
post:
|
||||
tags: [Public Booking]
|
||||
operationId: createBooking
|
||||
requestBody:
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/CreateBookingRequest"
|
||||
responses:
|
||||
"201":
|
||||
description: Booking created
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/CreateBookingResponse"
|
||||
/v1/dashboard/summary:
|
||||
get:
|
||||
tags: [Dashboard]
|
||||
operationId: getDashboardSummary
|
||||
security:
|
||||
- bearerAuth: []
|
||||
responses:
|
||||
"200":
|
||||
description: Tenant dashboard summary
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/DashboardSummary"
|
||||
"401":
|
||||
description: Unauthorized
|
||||
/v1/tenants/bootstrap:
|
||||
get:
|
||||
tags: [Tenant]
|
||||
operationId: getTenantBootstrap
|
||||
security:
|
||||
- bearerAuth: []
|
||||
responses:
|
||||
"200":
|
||||
description: Tenant bootstrap payload for the authenticated user
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/TenantBootstrap"
|
||||
"401":
|
||||
description: Unauthorized
|
||||
/v1/tenants/onboard:
|
||||
post:
|
||||
tags: [Tenant]
|
||||
operationId: onboardTenant
|
||||
security:
|
||||
- bearerAuth: []
|
||||
requestBody:
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/OnboardTenantRequest"
|
||||
responses:
|
||||
"201":
|
||||
description: Tenant created for authenticated user
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/TenantBootstrap"
|
||||
"400":
|
||||
description: Invalid request
|
||||
"401":
|
||||
description: Unauthorized
|
||||
"409":
|
||||
description: Conflict
|
||||
/v1/billing/subscription:
|
||||
get:
|
||||
tags: [Billing]
|
||||
operationId: getSubscriptionSnapshot
|
||||
security:
|
||||
- bearerAuth: []
|
||||
responses:
|
||||
"200":
|
||||
description: Current subscription snapshot and entitlements
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/SubscriptionSnapshot"
|
||||
"401":
|
||||
description: Unauthorized
|
||||
/v1/billing/checkout:
|
||||
post:
|
||||
tags: [Billing]
|
||||
operationId: createBillingCheckout
|
||||
security:
|
||||
- bearerAuth: []
|
||||
requestBody:
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/CheckoutSessionRequest"
|
||||
responses:
|
||||
"200":
|
||||
description: Hosted Stripe checkout session
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/CheckoutSessionResponse"
|
||||
"400":
|
||||
description: Invalid request
|
||||
"401":
|
||||
description: Unauthorized
|
||||
/v1/billing/refresh:
|
||||
post:
|
||||
tags: [Billing]
|
||||
operationId: refreshSubscriptionSnapshot
|
||||
security:
|
||||
- bearerAuth: []
|
||||
responses:
|
||||
"200":
|
||||
description: Refreshed snapshot
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/SubscriptionSnapshot"
|
||||
"401":
|
||||
description: Unauthorized
|
||||
/v1/webhooks/stripe:
|
||||
post:
|
||||
tags: [Billing]
|
||||
operationId: handleStripeWebhook
|
||||
requestBody:
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
responses:
|
||||
"200":
|
||||
description: Webhook accepted
|
||||
/v1/internal/jobs/reminders/dispatch:
|
||||
post:
|
||||
tags: [Jobs]
|
||||
operationId: dispatchReminderJobs
|
||||
security:
|
||||
- jobRunnerKey: []
|
||||
requestBody:
|
||||
required: false
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/DispatchReminderJobsRequest"
|
||||
responses:
|
||||
"200":
|
||||
description: Reminder jobs dispatched
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/DispatchReminderJobsResponse"
|
||||
"401":
|
||||
description: Unauthorized
|
||||
components:
|
||||
securitySchemes:
|
||||
bearerAuth:
|
||||
type: http
|
||||
scheme: bearer
|
||||
bearerFormat: JWT
|
||||
jobRunnerKey:
|
||||
type: apiKey
|
||||
in: header
|
||||
name: X-Bookra-Job-Key
|
||||
schemas:
|
||||
HealthResponse:
|
||||
type: object
|
||||
required: [status, environment]
|
||||
properties:
|
||||
status:
|
||||
type: string
|
||||
example: ok
|
||||
environment:
|
||||
type: string
|
||||
example: staging
|
||||
databaseConfigured:
|
||||
type: boolean
|
||||
PublicConfig:
|
||||
type: object
|
||||
required: [environment, neonAuthEnabled]
|
||||
properties:
|
||||
environment:
|
||||
type: string
|
||||
neonAuthEnabled:
|
||||
type: boolean
|
||||
apiUrl:
|
||||
type: string
|
||||
format: uri
|
||||
TimeSlot:
|
||||
type: object
|
||||
required: [startsAt, endsAt, mode]
|
||||
properties:
|
||||
serviceId:
|
||||
type: string
|
||||
format: uuid
|
||||
nullable: true
|
||||
classSessionId:
|
||||
type: string
|
||||
format: uuid
|
||||
nullable: true
|
||||
staffId:
|
||||
type: string
|
||||
format: uuid
|
||||
nullable: true
|
||||
locationId:
|
||||
type: string
|
||||
format: uuid
|
||||
nullable: true
|
||||
startsAt:
|
||||
type: string
|
||||
format: date-time
|
||||
endsAt:
|
||||
type: string
|
||||
format: date-time
|
||||
mode:
|
||||
type: string
|
||||
enum: [appointment, class]
|
||||
label:
|
||||
type: string
|
||||
remainingCapacity:
|
||||
type: integer
|
||||
nullable: true
|
||||
PublicAvailabilityResponse:
|
||||
type: object
|
||||
required: [tenantSlug, timezone, locale, slots]
|
||||
properties:
|
||||
tenantSlug:
|
||||
type: string
|
||||
timezone:
|
||||
type: string
|
||||
locale:
|
||||
type: string
|
||||
enum: [cs, en]
|
||||
slots:
|
||||
type: array
|
||||
items:
|
||||
$ref: "#/components/schemas/TimeSlot"
|
||||
CreateBookingRequest:
|
||||
type: object
|
||||
required: [tenantSlug, bookingMode, customerName, customerEmail, startsAt, endsAt]
|
||||
properties:
|
||||
tenantSlug:
|
||||
type: string
|
||||
bookingMode:
|
||||
type: string
|
||||
enum: [appointment, class]
|
||||
serviceId:
|
||||
type: string
|
||||
format: uuid
|
||||
classSessionId:
|
||||
type: string
|
||||
format: uuid
|
||||
staffId:
|
||||
type: string
|
||||
format: uuid
|
||||
locationId:
|
||||
type: string
|
||||
format: uuid
|
||||
customerName:
|
||||
type: string
|
||||
customerEmail:
|
||||
type: string
|
||||
format: email
|
||||
notes:
|
||||
type: string
|
||||
startsAt:
|
||||
type: string
|
||||
format: date-time
|
||||
endsAt:
|
||||
type: string
|
||||
format: date-time
|
||||
CreateBookingResponse:
|
||||
type: object
|
||||
required: [bookingId, reference, status]
|
||||
properties:
|
||||
bookingId:
|
||||
type: string
|
||||
format: uuid
|
||||
reference:
|
||||
type: string
|
||||
status:
|
||||
type: string
|
||||
enum: [confirmed, waitlisted]
|
||||
DashboardKPI:
|
||||
type: object
|
||||
required: [code, label, value]
|
||||
properties:
|
||||
code:
|
||||
type: string
|
||||
label:
|
||||
type: string
|
||||
value:
|
||||
type: string
|
||||
DashboardSummary:
|
||||
type: object
|
||||
required: [tenantName, locale, timezone, planCode, kpis]
|
||||
properties:
|
||||
tenantName:
|
||||
type: string
|
||||
locale:
|
||||
type: string
|
||||
timezone:
|
||||
type: string
|
||||
planCode:
|
||||
type: string
|
||||
kpis:
|
||||
type: array
|
||||
items:
|
||||
$ref: "#/components/schemas/DashboardKPI"
|
||||
TenantBootstrap:
|
||||
type: object
|
||||
required: [tenantId, tenantName, preset, locale, timezone, currentUser]
|
||||
properties:
|
||||
tenantId:
|
||||
type: string
|
||||
format: uuid
|
||||
tenantName:
|
||||
type: string
|
||||
preset:
|
||||
type: string
|
||||
locale:
|
||||
type: string
|
||||
timezone:
|
||||
type: string
|
||||
planCode:
|
||||
type: string
|
||||
currentUser:
|
||||
type: object
|
||||
required: [subject, role]
|
||||
properties:
|
||||
subject:
|
||||
type: string
|
||||
email:
|
||||
type: string
|
||||
format: email
|
||||
name:
|
||||
type: string
|
||||
role:
|
||||
type: string
|
||||
OnboardTenantRequest:
|
||||
type: object
|
||||
required: [name, slug, preset, locale, timezone]
|
||||
properties:
|
||||
name:
|
||||
type: string
|
||||
slug:
|
||||
type: string
|
||||
preset:
|
||||
type: string
|
||||
enum: [salon, clinic, massage, repair, studio]
|
||||
locale:
|
||||
type: string
|
||||
enum: [cs, en]
|
||||
timezone:
|
||||
type: string
|
||||
PlanEntitlements:
|
||||
type: object
|
||||
required: [maxLocations, maxStaff, smsAddonAvailable, advancedReporting]
|
||||
properties:
|
||||
maxLocations:
|
||||
type: integer
|
||||
maxStaff:
|
||||
type: integer
|
||||
smsAddonAvailable:
|
||||
type: boolean
|
||||
advancedReporting:
|
||||
type: boolean
|
||||
SubscriptionSnapshot:
|
||||
type: object
|
||||
required: [tenantId, customerId, subscriptionId, status, planCode, priceId, cancelAtPeriodEnd, entitlements]
|
||||
properties:
|
||||
tenantId:
|
||||
type: string
|
||||
format: uuid
|
||||
customerId:
|
||||
type: string
|
||||
subscriptionId:
|
||||
type: string
|
||||
status:
|
||||
type: string
|
||||
planCode:
|
||||
type: string
|
||||
priceId:
|
||||
type: string
|
||||
cancelAtPeriodEnd:
|
||||
type: boolean
|
||||
currentPeriodStart:
|
||||
type: string
|
||||
format: date-time
|
||||
nullable: true
|
||||
currentPeriodEnd:
|
||||
type: string
|
||||
format: date-time
|
||||
nullable: true
|
||||
paymentMethodBrand:
|
||||
type: string
|
||||
paymentMethodLast4:
|
||||
type: string
|
||||
entitlements:
|
||||
$ref: "#/components/schemas/PlanEntitlements"
|
||||
lastSyncedAt:
|
||||
type: string
|
||||
format: date-time
|
||||
nullable: true
|
||||
checkoutUrlAvailable:
|
||||
type: boolean
|
||||
CheckoutSessionRequest:
|
||||
type: object
|
||||
required: [planCode]
|
||||
properties:
|
||||
planCode:
|
||||
type: string
|
||||
enum: [starter, growth, multi-location]
|
||||
CheckoutSessionResponse:
|
||||
type: object
|
||||
required: [url]
|
||||
properties:
|
||||
url:
|
||||
type: string
|
||||
format: uri
|
||||
DispatchReminderJobsRequest:
|
||||
type: object
|
||||
properties:
|
||||
limit:
|
||||
type: integer
|
||||
minimum: 1
|
||||
maximum: 200
|
||||
DispatchReminderJobsResponse:
|
||||
type: object
|
||||
required: [processedCount, sentCount, failedCount]
|
||||
properties:
|
||||
processedCount:
|
||||
type: integer
|
||||
sentCount:
|
||||
type: integer
|
||||
failedCount:
|
||||
type: integer
|
||||
Reference in New Issue
Block a user