OpenAPI spec
OpenAPI spec
Last updated 5/24/2026
CNBS OpenAPI 3.1 Specification
Endpoint Summary Table
| # | Method | Path | Tag | Auth Required | Summary |
|---|---|---|---|---|---|
| 1 | POST | /api/admin/onboarding/complete | Admin | Yes | Complete admin onboarding |
| 2 | POST | /api/ai/extract-colors | AI | Yes | Extract color palette from image |
| 3 | POST | /api/ai/generate-hero | AI | Yes | Generate hero section content |
| 4 | POST | /api/ai/generate-image | AI | Yes | Generate AI image |
| 5 | POST | /api/ai/generate-promotion | AI | Yes | Generate promotional content |
| 6 | POST | /api/ai/save-generated-image | AI | Yes | Save a generated AI image |
| 7 | GET | /api/analytics/customers | Analytics | Yes | Get customer analytics |
| 8 | GET | /api/analytics/dashboard/performance | Analytics | Yes | Get dashboard performance metrics |
| 9 | GET | /api/analytics/dashboard/real-time | Analytics | Yes | Get real-time dashboard data |
| 10 | GET | /api/analytics/dashboard | Analytics | Yes | Get analytics dashboard summary |
| 11 | GET | /api/analytics/dashboard/trends | Analytics | Yes | Get dashboard trend data |
| 12 | GET | /api/analytics/insights | Analytics | Yes | Get AI-generated analytics insights |
| 13 | GET | /api/analytics/inventory-insights | Analytics | Yes | Get inventory analytics insights |
| 14 | GET | /api/analytics/inventory | Analytics | Yes | Get inventory analytics |
| 15 | GET | /api/analytics/performance | Analytics | Yes | Get performance analytics |
| 16 | GET | /api/analytics/predictions | Analytics | Yes | Get predictive analytics |
| 17 | GET | /api/analytics/reports/compliance | Analytics | Yes | Get compliance report |
| 18 | GET | /api/analytics/reports/inventory | Analytics | Yes | Get inventory report |
| 19 | GET | /api/analytics/reports | Analytics | Yes | List available reports |
| 20 | GET | /api/analytics/reports/sales | Analytics | Yes | Get sales report |
| 21 | GET | /api/analytics/revenue | Analytics | Yes | Get revenue analytics |
| 22 | GET | /api/analytics/vitals | Analytics | Yes | Get system vitals |
| 23 | GET | /api/associates | Associates | Yes | List associates |
| 24 | POST | /api/associates | Associates | Yes | Create associate |
| 25 | GET | /api/associates/{associateId} | Associates | Yes | Get associate by ID |
| 26 | PATCH | /api/associates/{associateId} | Associates | Yes | Update associate |
| 27 | DELETE | /api/associates/{associateId} | Associates | Yes | Delete associate |
| 28 | GET | /api/auth/check-role | Auth | Yes | Check current user role |
| 29 | GET | /api/auth/check-user-context | Auth | Yes | Check user organization context |
| 30 | POST | /api/auth/employee | Auth | No | Authenticate employee (PIN) |
| 31 | POST | /api/backup | Operations | Yes | Trigger data backup |
| 32 | GET | /api/canonical/brands | Canonical | Yes | List canonical cannabis brands |
| 33 | GET | /api/canonical/categories | Canonical | Yes | List canonical product categories |
| 34 | GET | /api/canonical/effects | Canonical | Yes | List canonical cannabis effects |
| 35 | POST | /api/careers/apply | Careers | No | Submit a job application |
| 36 | GET | /api/cash-drawer | Operations | Yes | Get cash drawer status |
| 37 | POST | /api/cash-drawer | Operations | Yes | Record cash drawer event |
| 38 | POST | /api/clerk/add-to-organization | Clerk | Yes | Add user to Clerk organization |
| 39 | POST | /api/clerk/sync/customer | Clerk | Yes | Sync customer record to Clerk |
| 40 | POST | /api/clerk/sync/membership/add | Clerk | Yes | Add organization membership |
| 41 | POST | /api/clerk/sync/membership/remove | Clerk | Yes | Remove organization membership |
| 42 | POST | /api/clerk/sync/organization | Clerk | Yes | Sync organization to Clerk |
| 43 | POST | /api/clerk/sync | Clerk | Yes | Full Clerk sync (webhook) |
| 44 | POST | /api/clerk/sync/user | Clerk | Yes | Sync user record to Clerk |
openapi: 3.1.0
info:
title: CNBS – Cannabis Business System API
version: 0.1.0
description: |
The CNBS API powers a multi-tenant cannabis dispensary platform (dispensary-pos)
built on Next.js 15. It covers point-of-sale operations, inventory management,
analytics, regulatory compliance, AI-assisted content generation, and Clerk-based
identity synchronisation across organisations.
**Authentication** – Every protected endpoint requires a valid Clerk session token
supplied as a Bearer token in the `Authorization` header. A small number of
public endpoints (employee PIN login, career applications) are explicitly exempt.
**Multi-tenancy** – Most resources are scoped to an `orgId` (Clerk organisation
ID). Callers without a matching organisation context will receive `403 Forbidden`.
**Versioning** – The API is currently at v0.1 (Spark stage). Breaking changes will
be communicated via changelog entries in `docs/ROADMAP.md`.
contact:
name: CNBS Engineering
url: https://github.com/midwestco/cnbs
email: engineering@cnbs.io
license:
name: Proprietary
identifier: LicenseRef-CNBS-1.0
servers:
- url: https://app.cnbs.io
description: Production
- url: https://staging.cnbs.io
description: Staging
- url: http://localhost:3000
description: Local development
# ---------------------------------------------------------------------------
# Security
# ---------------------------------------------------------------------------
security:
- ClerkBearerAuth: []
# ---------------------------------------------------------------------------
# Tags
# ---------------------------------------------------------------------------
tags:
- name: Admin
description: Onboarding and administrative setup operations
- name: AI
description: |
AI-powered content and image generation endpoints backed by
`@anthropic-ai/sdk` and `openai` (see `next.config.ts`).
- name: Analytics
description: |
Business intelligence: sales revenue, inventory insights, customer
segmentation, compliance reports, and real-time dashboard feeds.
- name: Associates
description: Dispensary employee (budtender/associate) management
- name: Auth
description: Authentication helpers – role checks and employee PIN login
- name: Canonical
description: |
Read-only reference data (brands, categories, effects) shared across
organisations for consistent product taxonomy.
- name: Careers
description: Public-facing job application intake
- name: Clerk
description: Clerk identity-platform synchronisation webhooks and utilities
- name: Operations
description: Physical store operations – cash drawer management and backups
# ---------------------------------------------------------------------------
# Paths
# ---------------------------------------------------------------------------
paths:
# ── Admin ─────────────────────────────────────────────────────────────────
/api/admin/onboarding/complete:
post:
operationId: completeAdminOnboarding
tags: [Admin]
summary: Complete admin onboarding
description: |
Marks the onboarding flow as complete for the calling administrator.
Persists organisation metadata and triggers initial data seeding such
as default product categories and tax configurations.
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/AdminOnboardingCompleteRequest'
responses:
'200':
description: Onboarding completed successfully
content:
application/json:
schema:
$ref: '#/components/schemas/AdminOnboardingCompleteResponse'
'400':
$ref: '#/components/responses/BadRequest'
'401':
$ref: '#/components/responses/Unauthorized'
'500':
$ref: '#/components/responses/InternalServerError'
# ── AI ────────────────────────────────────────────────────────────────────
/api/ai/extract-colors:
post:
operationId: aiExtractColors
tags: [AI]
summary: Extract color palette from image
description: |
Analyses a supplied image URL or base64 payload and returns a structured
color palette (primary, secondary, accent) suitable for storefront
theming. Backed by Anthropic Claude vision capabilities.
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/ExtractColorsRequest'
responses:
'200':
description: Color palette extracted
content:
application/json:
schema:
$ref: '#/components/schemas/ExtractColorsResponse'
'400':
$ref: '#/components/responses/BadRequest'
'401':
$ref: '#/components/responses/Unauthorized'
'500':
$ref: '#/components/responses/InternalServerError'
/api/ai/generate-hero:
post:
operationId: aiGenerateHero
tags: [AI]
summary: Generate hero section content
description: |
Generates headline copy, subheadline, and a call-to-action label for the
dispensary storefront hero banner. Accepts brand tone parameters and
optional seasonal context.
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/GenerateHeroRequest'
responses:
'200':
description: Hero content generated
content:
application/json:
schema:
$ref: '#/components/schemas/GenerateHeroResponse'
'400':
$ref: '#/components/responses/BadRequest'
'401':
$ref: '#/components/responses/Unauthorized'
'500':
$ref: '#/components/responses/InternalServerError'
/api/ai/generate-image:
post:
operationId: aiGenerateImage
tags: [AI]
summary: Generate AI image
description: |
Generates a product or marketing image via the OpenAI Images API.
Returns the generated image as a URL. Caller should subsequently
call `/api/ai/save-generated-image` to persist the asset to Supabase
Storage.
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/GenerateImageRequest'
responses:
'200':
description: Image generated successfully
content:
application/json:
schema:
$ref: '#/components/schemas/GenerateImageResponse'
'400':
$ref: '#/components/responses/BadRequest'
'401':
$ref: '#/components/responses/Unauthorized'
'500':
$ref: '#/components/responses/InternalServerError'
/api/ai/generate-promotion:
post:
operationId: aiGeneratePromotion
tags: [AI]
summary: Generate promotional content
description: |
Creates promotional copy for banners, push notifications, or email
campaigns. Accepts product IDs and desired discount information to
produce contextually relevant marketing language.
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/GeneratePromotionRequest'
responses:
'200':
description: Promotion content generated
content:
application/json:
schema:
$ref: '#/components/schemas/GeneratePromotionResponse'
'400':
$ref: '#/components/responses/BadRequest'
'401':
$ref: '#/components/responses/Unauthorized'
'500':
$ref: '#/components/responses/InternalServerError'
/api/ai/save-generated-image:
post:
operationId: aiSaveGeneratedImage
tags: [AI]
summary: Save a generated AI image
description: |
Downloads the OpenAI-hosted image URL and persists it to Supabase
Storage under the organisation's asset bucket. Returns the permanent
Supabase public URL.
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/SaveGeneratedImageRequest'
responses:
'200':
description: Image saved to storage
content:
application/json:
schema:
$ref: '#/components/schemas/SaveGeneratedImageResponse'
'400':
$ref: '#/components/responses/BadRequest'
'401':
$ref: '#/components/responses/Unauthorized'
'500':
$ref: '#/components/responses/InternalServerError'
# ── Analytics ─────────────────────────────────────────────────────────────
/api/analytics/customers:
get:
operationId: getCustomerAnalytics
tags: [Analytics]
summary: Get customer analytics
description: |
Returns aggregated customer metrics including new vs. returning visitor
ratios, average order value, purchase frequency, and top customer
segments for the authenticated organisation.
parameters:
- $ref: '#/components/parameters/DateFrom'
- $ref: '#/components/parameters/DateTo'
- $ref: '#/components/parameters/OrgIdQuery'
responses:
'200':
description: Customer analytics data
content:
application/json:
schema:
$ref: '#/components/schemas/CustomerAnalyticsResponse'
'400':
$ref: '#/components/responses/BadRequest'
'401':
$ref: '#/components/responses/Unauthorized'
'500':
$ref: '#/components/responses/InternalServerError'
/api/analytics/dashboard:
get:
operationId: getAnalyticsDashboard
tags: [Analytics]
summary: Get analytics dashboard summary
description: |
Returns a rolled-up summary of key performance indicators: total
revenue, transaction count, average basket size, top-selling products,
and compliance status for the current period.
parameters:
- $ref: '#/components/parameters/DateFrom'
- $ref: '#/components/parameters/DateTo'
- $ref: '#/components/parameters/OrgIdQuery'
responses:
'200':
description: Dashboard summary
content:
application/json:
schema:
$ref: '#/components/schemas/DashboardSummaryResponse'
'400':
$ref: '#/components/responses/BadRequest'
'401':
$ref: '#/components/responses/Unauthorized'
'500':
$ref: '#/components/responses/InternalServerError'
/api/analytics/dashboard/performance:
get:
operationId: getDashboardPerformance
tags: [Analytics]
summary: Get dashboard performance metrics
description: |
Returns server-side performance metrics for the dashboard itself
(API latency p50/p95/p99, cache hit-rate, database query counts)
alongside application KPIs.
parameters:
- $ref: '#/components/parameters/OrgIdQuery'
responses:
'200':
description: Performance metrics
content:
application/json:
schema:
$ref: '#/components/schemas/DashboardPerformanceResponse'
'401':
$ref: '#/components/responses/Unauthorized'
'500':
$ref: '#/components/responses/InternalServerError'
/api/analytics/dashboard/real-time:
get:
operationId: getDashboardRealTime
tags: [Analytics]
summary: Get real-time dashboard data
description: |
Streams live metrics via polling or Server-Sent Events: current active
POS sessions, transactions in the last 15 minutes, and live inventory
depletion rates. Backed by Supabase Realtime.
parameters:
- $ref: '#/components/parameters/OrgIdQuery'
responses:
'200':
description: Real-time dashboard snapshot
content:
application/json:
schema:
$ref: '#/components/schemas/RealTimeDashboardResponse'
'401':
$ref: '#/components/responses/Unauthorized'
'500':
$ref: '#/components/responses/InternalServerError'
/api/analytics/dashboard/trends:
get:
operationId: getDashboardTrends
tags: [Analytics]
summary: Get dashboard trend data
description: |
Returns time-series data points for revenue, transaction volume, and
customer acquisition across configurable granularities (hourly, daily,
weekly, monthly).
parameters:
- $ref: '#/components/parameters/DateFrom'
- $ref: '#/components/parameters/DateTo'
- $ref: '#/components/parameters/OrgIdQuery'
- name: granularity
in: query
required: false
schema:
type: string
enum: [hourly, daily, weekly, monthly]
default: daily
description: Time bucket granularity for trend series
responses:
'200':
description: Trend time-series data
content:
application/json:
schema:
$ref: '#/components/schemas/TrendsResponse'
'400':
$ref: '#/components/responses/BadRequest'
'401':
$ref: '#/components/responses/Unauthorized'
'500':
$ref: '#/components/responses/InternalServerError'
/api/analytics/insights:
get:
operationId: getAnalyticsInsights
tags: [Analytics]
summary: Get AI-generated analytics insights
description: |
Runs AI analysis over recent sales and inventory data to surface
actionable insights such as slow-moving SKUs, reorder recommendations,
and demand forecast alerts.
parameters:
- $ref: '#/components/parameters/OrgIdQuery'
responses:
'200':
description: AI insights
content:
application/json:
schema:
$ref: '#/components/schemas/AnalyticsInsightsResponse'
'401':
$ref: '#/components/responses/Unauthorized'
'500':
$ref: '#/components/responses/InternalServerError'
/api/analytics/inventory-insights:
get:
operationId: getInventoryInsights
tags: [Analytics]
summary: Get inventory analytics insights
description: |
Returns deep-dive inventory metrics: stock turnover ratio, days on
hand by category, shrinkage rate, and compliance variance between
physical counts and METRC-reported quantities.
parameters:
- $ref: '#/components/parameters/DateFrom'
- $ref: '#/components/parameters/DateTo'
- $ref: '#/components/parameters/OrgIdQuery'
responses:
'200':
description: Inventory insights
content:
application/json:
schema:
$ref: '#/components/schemas/InventoryInsightsResponse'
'400':
$ref: '#/components/responses/BadRequest'
'401':
$ref: '#/components/responses/Unauthorized'
'500':
$ref: '#/components/responses/InternalServerError'
/api/analytics/inventory:
get:
operationId: getInventoryAnalytics
tags: [Analytics]
summary: Get inventory analytics
description: |
Aggregated inventory analytics including on-hand quantities by category,
product velocity, pending transfers, and low-stock alerts.
parameters:
- $ref: '#/components/parameters/OrgIdQuery'
responses:
'200':
description: Inventory analytics
content:
application/json:
schema:
$ref: '#/components/schemas/InventoryAnalyticsResponse'
'401':
$ref: '#/components/responses/Unauthorized'
'500':
$ref: '#/components/responses/InternalServerError'
/api/analytics/performance:
get:
operationId: getPerformanceAnalytics
tags: [Analytics]
summary: Get performance analytics
description: |
Employee and POS-station performance metrics including transactions per
hour, average transaction time, upsell rate, and return rate by
associate.
parameters:
- $ref: '#/components/parameters/DateFrom'
- $ref: '#/components/parameters/DateTo'
- $ref: '#/components/parameters/OrgIdQuery'
responses:
'200':
description: Performance analytics
content:
application/json:
schema:
$ref: '#/components/schemas/PerformanceAnalyticsResponse'
'400':
$ref: '#/components/responses/BadRequest'
'401':
$ref: '#/components/responses/Unauthorized'
'500':
$ref: '#/components/responses/InternalServerError'
/api/analytics/predictions:
get:
operationId: getAnalyticsPredictions
tags: [Analytics]
summary: Get predictive analytics
description: |
Machine-learning–driven demand forecasts, projected revenue for the
next 7/30 days, and reorder point predictions by SKU.
parameters:
- $ref: '#/components/parameters/OrgIdQuery'
- name: horizon
in: query
required: false
schema:
type: integer
enum: [7, 30, 90]
default: 30
description: Forecast horizon in days
responses:
'200':
description: Predictive analytics
content:
application/json:
schema:
$ref: '#/components/schemas/PredictionsResponse'
'401':
$ref: '#/components/responses/Unauthorized'
'500':
$ref: '#/components/responses/InternalServerError'
/api/analytics/reports:
get:
operationId: listReports
tags: [Analytics]
summary: List available reports
description: |
Returns metadata for all saved and scheduled reports available to the
organisation, including report type, last run time, and download URL.
parameters:
- $ref: '#/components/parameters/OrgIdQuery'
responses:
'200':
description: List of reports
content:
application/json:
schema:
$ref: '#/components/schemas/ReportsListResponse'
'401':
$ref: '#/components/responses/Unauthorized'
'500':
$ref: '#/components/responses/InternalServerError'
/api/analytics/reports/compliance:
get:
operationId: getComplianceReport
tags: [Analytics]
summary: Get compliance report
description: |
Generates or retrieves a compliance report containing METRC transfer
manifest reconciliation, purchase limit adherence, and state-mandated
sales data for the specified date range.
parameters:
- $ref: '#/components/parameters/DateFrom'
- $ref: '#/components/parameters/DateTo'
- $ref: '#/components/parameters/OrgIdQuery'
responses:
'200':
description: Compliance report
content:
application/json:
schema:
$ref: '#/components/schemas/ComplianceReportResponse'
'400':
$ref: '#/components/responses/BadRequest'
'401':
$ref: '#/components/responses/Unauthorized'
'500':
$ref: '#/components/responses/InternalServerError'
/api/analytics/reports/inventory:
get:
operationId: getInventoryReport
tags: [Analytics]
summary: Get inventory report
description: |
Returns a paginated inventory snapshot report with on-hand quantities,
unit cost, retail value, and days-on-hand, filterable by category and
vendor.
parameters:
- $ref: '#/components/parameters/DateFrom'
- $ref: '#/components/parameters/DateTo'
- $ref: '#/components/parameters/OrgIdQuery'
- name: category
in: query
required: false
schema:
type: string
description: Filter by canonical product category
responses:
'200':
description: Inventory report
content:
application/json:
schema:
$ref: '#/components/schemas/InventoryReportResponse'
'400':
$ref: '#/components/responses/BadRequest'
'401':
$ref: '#/components/responses/Unauthorized'
'500':
$ref: '#/components/responses/InternalServerError'
/api/analytics/reports/sales:
get:
operationId: getSalesReport
tags: [Analytics]
summary: Get sales report
description: |
Returns a detailed sales report broken down by product, category,
payment method, and associate. Supports CSV export via the `format`
query parameter.
parameters:
- $ref: '#/components/parameters/DateFrom'
- $ref: '#/components/parameters/DateTo'
- $ref: '#/components/parameters/OrgIdQuery'
- name: format
in: query
required: false
schema:
type: string
enum: [json, csv]
default: json
description: Response format
responses:
'200':
description: Sales report
content:
application/json:
schema:
$ref: '#/components/schemas/SalesReportResponse'
text/csv:
schema:
type: string
format: binary
'400':
$ref: '#/components/responses/BadRequest'
'401':
$ref: '#/components/responses/Unauthorized'
'500':
$ref: '#/components/responses/InternalServerError'
/api/analytics/revenue:
get:
operationId: getRevenueAnalytics
tags: [Analytics]
summary: Get revenue analytics
description: |
Gross revenue, net revenue (after discounts and returns), tax collected,
and margin metrics for the organisation and specified period.
parameters:
- $ref: '#/components/parameters/DateFrom'
- $ref: '#/components/parameters/DateTo'
- $ref: '#/components/parameters/OrgIdQuery'
responses:
'200':
description: Revenue analytics
content:
application/json:
schema:
$ref: '#/components/schemas/RevenueAnalyticsResponse'
'400':
$ref: '#/components/responses/BadRequest'
'401':
$ref: '#/components/responses/Unauthorized'
'500':
$ref: '#/components/responses/InternalServerError'
/api/analytics/vitals:
get:
operationId: getAnalyticsVitals
tags: [Analytics]
summary: Get system vitals
description: |
System health metrics: database connection pool utilisation, Supabase
Realtime connection count, cache hit ratio, and last successful METRC
sync timestamp.
parameters:
- $ref: '#/components/parameters/OrgIdQuery'
responses:
'200':
description: System vitals
content:
application/json:
schema:
$ref: '#/components/schemas/VitalsResponse'
'401':
$ref: '#/components/responses/Unauthorized'
'500':
$ref: '#/components/responses/InternalServerError'
# ── Associates ────────────────────────────────────────────────────────────
/api/associates:
get:
operationId: listAssociates
tags: [Associates]
summary: List associates
description: |
Returns all budtenders and associates belonging to the authenticated
organisation, including role, active status, and assigned POS station.
parameters:
- $ref: '#/components/parameters/OrgIdQuery'
- name: active
in: query
required: false
schema:
type: boolean
description: Filter to active (true) or inactive (false) associates only
responses:
'200':
description: List of associates
content:
application/json:
schema:
$ref: '#/components/schemas/AssociatesListResponse'
'401':
$ref: '#/components/responses/Unauthorized'
'500':
$ref: '#/components/responses/InternalServerError'
post:
operationId: createAssociate
tags: [Associates]
summary: Create associate
description: |
Creates a new associate record and optionally sends a Clerk invitation
to the supplied email address.
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/CreateAssociateRequest'
responses:
'200':
description: Associate created
content:
application/json:
schema:
$ref: '#/components/schemas/Associate'
'400':
$ref: '#/components/responses/BadRequest'
'401':
$ref: '#/components/responses/Unauthorized'
'500':
$ref: '#/components/responses/InternalServerError'
/api/associates/{associateId}:
parameters:
- name: associateId
in: path
required: true
schema:
type: string
format: uuid
description: UUID of the associate record
get:
operationId: getAssociate
tags: [Associates]
summary: Get associate by ID
description: Returns the full profile of a single associate.
responses:
'200':
description: Associate record
content:
application/json:
schema:
$ref: '#/components/schemas/Associate'
'401':
$ref: '#/components/responses/Unauthorized'
'404':
$ref: '#/components/responses/NotFound'
'500':
$ref: '#/components/responses/InternalServerError'
patch:
operationId: updateAssociate
tags: [Associates]
summary: Update associate
description: Partially updates an associate record.
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/UpdateAssociateRequest'
responses:
'200':
description: Updated associate record
content:
application/json:
schema:
$ref: '#/components/schemas/Associate'
'400':
$ref: '#/components/responses/BadRequest'
'401':
$ref: '#/components/responses/Unauthorized'
'404':
$ref: '#/components/responses/NotFound'
'500':
$ref: '#/components/responses/InternalServerError'
delete:
operationId: deleteAssociate
tags: [Associates]
summary: Delete associate
description: |
Soft-deletes the associate record, revokes Clerk organisation membership,
and marks any open POS sessions as closed.
responses:
'200':
description: Associate deleted
content:
application/json:
schema:
$ref: '#/components/schemas/DeleteResponse'
'401':
$ref: '#/components/responses/Unauthorized'
'404':
$ref: '#/components/responses/NotFound'
'500':
$ref: '#/components/responses/InternalServerError'
# ── Auth ──────────────────────────────────────────────────────────────────
/api/auth/check-role:
get:
operationId: checkRole
tags: [Auth]
summary: