This commit is contained in:
Tomas Dvorak
2026-05-05 09:48:07 +02:00
parent d854614a87
commit 48c3e15a38
295 changed files with 178381 additions and 1039 deletions
+214 -12
View File
@@ -4,7 +4,7 @@ info:
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.
scheduling logic, tenant isolation, and Paddle-backed plan enforcement.
servers:
- url: http://localhost:8080
tags:
@@ -155,15 +155,17 @@ paths:
$ref: "#/components/schemas/CheckoutSessionRequest"
responses:
"200":
description: Hosted Stripe checkout session
description: Paddle checkout launch payload
content:
application/json:
schema:
$ref: "#/components/schemas/CheckoutSessionResponse"
$ref: "#/components/schemas/CheckoutLaunchResponse"
"400":
description: Invalid request
"401":
description: Unauthorized
"503":
description: Billing provider unavailable
/v1/billing/refresh:
post:
tags: [Billing]
@@ -179,10 +181,31 @@ paths:
$ref: "#/components/schemas/SubscriptionSnapshot"
"401":
description: Unauthorized
/v1/webhooks/stripe:
"503":
description: Billing provider unavailable
/v1/billing/portal:
post:
tags: [Billing]
operationId: handleStripeWebhook
operationId: createBillingPortalSession
security:
- bearerAuth: []
responses:
"200":
description: Paddle customer portal session
content:
application/json:
schema:
$ref: "#/components/schemas/PortalSessionResponse"
"400":
description: Billing customer missing
"401":
description: Unauthorized
"503":
description: Billing provider unavailable
/v1/webhooks/paddle:
post:
tags: [Billing]
operationId: handlePaddleWebhook
requestBody:
required: true
content:
@@ -238,7 +261,7 @@ components:
type: boolean
PublicConfig:
type: object
required: [environment, neonAuthEnabled]
required: [environment, neonAuthEnabled, apiUrl, demoMode]
properties:
environment:
type: string
@@ -247,6 +270,8 @@ components:
apiUrl:
type: string
format: uri
demoMode:
type: boolean
TimeSlot:
type: object
required: [startsAt, endsAt, mode]
@@ -354,20 +379,84 @@ components:
type: string
DashboardSummary:
type: object
required: [tenantName, locale, timezone, planCode, kpis]
required: [tenantName, tenantSlug, locale, timezone, planCode, publicBookingUrl, setupCompletion, kpis]
properties:
tenantName:
type: string
tenantSlug:
type: string
locale:
type: string
timezone:
type: string
planCode:
type: string
publicBookingUrl:
type: string
setupCompletion:
type: integer
kpis:
type: array
items:
$ref: "#/components/schemas/DashboardKPI"
upcomingBookings:
type: array
items:
$ref: "#/components/schemas/UpcomingBooking"
widgetSnippets:
type: array
items:
$ref: "#/components/schemas/WidgetSnippet"
tracking:
$ref: "#/components/schemas/TrackingStatus"
UpcomingBooking:
type: object
properties:
reference:
type: string
customerName:
type: string
customerEmail:
type: string
startsAt:
type: string
format: date-time
endsAt:
type: string
format: date-time
status:
type: string
label:
type: string
WidgetSnippet:
type: object
properties:
kind:
type: string
code:
type: string
TrackingStatus:
type: object
properties:
provider:
type: string
connected:
type: boolean
siteId:
type: string
message:
type: string
BrandProfile:
type: object
properties:
name:
type: string
siteUrl:
type: string
logoUrl:
type: string
primaryColor:
type: string
TenantBootstrap:
type: object
required: [tenantId, tenantName, preset, locale, timezone, currentUser]
@@ -377,6 +466,8 @@ components:
format: uuid
tenantName:
type: string
tenantSlug:
type: string
preset:
type: string
locale:
@@ -385,6 +476,10 @@ components:
type: string
planCode:
type: string
onboardingCompleted:
type: boolean
brand:
$ref: "#/components/schemas/BrandProfile"
currentUser:
type: object
required: [subject, role]
@@ -414,25 +509,84 @@ components:
enum: [cs, en]
timezone:
type: string
brand:
$ref: "#/components/schemas/BrandProfile"
locationName:
type: string
bookingDefaults:
$ref: "#/components/schemas/BookingDefaultsRequest"
availabilityBlocks:
type: array
items:
$ref: "#/components/schemas/AvailabilityBlockRequest"
teamInvites:
type: array
items:
$ref: "#/components/schemas/TeamInviteRequest"
BookingDefaultsRequest:
type: object
properties:
serviceName:
type: string
durationMinutes:
type: integer
bufferBeforeMinutes:
type: integer
bufferAfterMinutes:
type: integer
cancelWindowHours:
type: integer
AvailabilityBlockRequest:
type: object
required: [dayOfWeek, startsLocal, endsLocal]
properties:
dayOfWeek:
type: integer
minimum: 1
maximum: 7
startsLocal:
type: string
example: "09:00"
endsLocal:
type: string
example: "17:00"
busy:
type: boolean
TeamInviteRequest:
type: object
required: [email]
properties:
email:
type: string
format: email
role:
type: string
PlanEntitlements:
type: object
required: [maxLocations, maxStaff, smsAddonAvailable, advancedReporting]
required: [maxLocations, maxStaff, emailReminders, advancedReporting, widgetEmbedding, umamiTracking]
properties:
maxLocations:
type: integer
maxStaff:
type: integer
smsAddonAvailable:
emailReminders:
type: boolean
widgetEmbedding:
type: boolean
umamiTracking:
type: boolean
advancedReporting:
type: boolean
SubscriptionSnapshot:
type: object
required: [tenantId, customerId, subscriptionId, status, planCode, priceId, cancelAtPeriodEnd, entitlements]
required: [tenantId, provider, customerId, subscriptionId, status, planCode, currency, priceId, cancelAtPeriodEnd, entitlements, displayPrices, trialDays, checkoutUrlAvailable, syncAvailable, portalAvailable]
properties:
tenantId:
type: string
format: uuid
provider:
type: string
example: paddle
customerId:
type: string
subscriptionId:
@@ -441,6 +595,9 @@ components:
type: string
planCode:
type: string
currency:
type: string
enum: [czk, usd, eur]
priceId:
type: string
cancelAtPeriodEnd:
@@ -459,20 +616,65 @@ components:
type: string
entitlements:
$ref: "#/components/schemas/PlanEntitlements"
displayPrices:
type: array
items:
$ref: "#/components/schemas/PlanDisplayPrice"
trialDays:
type: integer
lastSyncedAt:
type: string
format: date-time
nullable: true
checkoutUrlAvailable:
type: boolean
syncAvailable:
type: boolean
portalAvailable:
type: boolean
CheckoutSessionRequest:
type: object
required: [planCode]
properties:
planCode:
type: string
enum: [starter, growth, multi-location]
CheckoutSessionResponse:
enum: [starter, pro, business]
currency:
type: string
enum: [czk, usd]
PlanDisplayPrice:
type: object
required: [currency, amountCents, formatted]
properties:
currency:
type: string
enum: [czk, usd]
amountCents:
type: integer
formatted:
type: string
CheckoutLaunchResponse:
type: object
required: [priceId, successRedirectUrl, cancelRedirectUrl, customData]
properties:
priceId:
type: string
customerId:
type: string
customerEmail:
type: string
format: email
successRedirectUrl:
type: string
format: uri
cancelRedirectUrl:
type: string
format: uri
customData:
type: object
additionalProperties:
type: string
PortalSessionResponse:
type: object
required: [url]
properties: