aee0f09db8
- Datafabrik: Dockerfile fix, agentorkestrering fungerar - Vision: Identify-modell, FAISS, OCR alla testade - API: Alla 7 integrationstester passerade - Upplösare: Entitetsupplösning verifierad
741 lines
20 KiB
YAML
741 lines
20 KiB
YAML
openapi: 3.1.0
|
|
info:
|
|
title: LandveX Enterprise Platform Admin API
|
|
version: 1.0.0
|
|
description: Admin backend API for LandveX Enterprise Platform
|
|
servers:
|
|
- url: https://api.landvex.com/v1
|
|
description: Production
|
|
- url: https://api-staging.landvex.com/v1
|
|
description: Staging
|
|
|
|
security:
|
|
- BearerAuth: []
|
|
- ApiKeyAuth: []
|
|
|
|
paths:
|
|
# Auth
|
|
/auth/login:
|
|
post:
|
|
tags: [Auth]
|
|
summary: Login with email/password
|
|
security: []
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
required: [email, password]
|
|
properties:
|
|
email: { type: string, format: email }
|
|
password: { type: string, minLength: 8 }
|
|
mfa_code: { type: string }
|
|
responses:
|
|
'200':
|
|
description: Login successful
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
access_token: { type: string }
|
|
refresh_token: { type: string }
|
|
token_type: { type: string, default: Bearer }
|
|
expires_in: { type: integer }
|
|
mfa_required: { type: boolean }
|
|
|
|
/auth/refresh:
|
|
post:
|
|
tags: [Auth]
|
|
summary: Refresh access token
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
required: [refresh_token]
|
|
properties:
|
|
refresh_token: { type: string }
|
|
responses:
|
|
'200':
|
|
description: New tokens issued
|
|
|
|
# Tenants
|
|
/tenants:
|
|
get:
|
|
tags: [Tenants]
|
|
summary: List tenants
|
|
parameters:
|
|
- name: page
|
|
in: query
|
|
schema: { type: integer, default: 1 }
|
|
- name: per_page
|
|
in: query
|
|
schema: { type: integer, default: 20 }
|
|
- name: type
|
|
in: query
|
|
schema: { type: string, enum: [municipality, enterprise, partner] }
|
|
- name: status
|
|
in: query
|
|
schema: { type: string, enum: [active, suspended, cancelled, trial] }
|
|
- name: search
|
|
in: query
|
|
schema: { type: string }
|
|
responses:
|
|
'200':
|
|
description: List of tenants
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
data:
|
|
type: array
|
|
items: { $ref: '#/components/schemas/Tenant' }
|
|
meta: { $ref: '#/components/schemas/PaginationMeta' }
|
|
|
|
post:
|
|
tags: [Tenants]
|
|
summary: Create tenant
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema: { $ref: '#/components/schemas/TenantCreate' }
|
|
responses:
|
|
'201':
|
|
description: Tenant created
|
|
content:
|
|
application/json:
|
|
schema: { $ref: '#/components/schemas/Tenant' }
|
|
|
|
/tenants/{id}:
|
|
parameters:
|
|
- name: id
|
|
in: path
|
|
required: true
|
|
schema: { type: string, format: uuid }
|
|
get:
|
|
tags: [Tenants]
|
|
summary: Get tenant details
|
|
responses:
|
|
'200':
|
|
description: Tenant details
|
|
content:
|
|
application/json:
|
|
schema: { $ref: '#/components/schemas/Tenant' }
|
|
patch:
|
|
tags: [Tenants]
|
|
summary: Update tenant
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema: { $ref: '#/components/schemas/TenantUpdate' }
|
|
responses:
|
|
'200':
|
|
description: Tenant updated
|
|
delete:
|
|
tags: [Tenants]
|
|
summary: Delete tenant (soft)
|
|
responses:
|
|
'204':
|
|
description: Tenant deleted
|
|
|
|
# Users
|
|
/users:
|
|
get:
|
|
tags: [Users]
|
|
summary: List users
|
|
parameters:
|
|
- name: tenant_id
|
|
in: header
|
|
required: true
|
|
schema: { type: string, format: uuid }
|
|
- name: page
|
|
in: query
|
|
schema: { type: integer, default: 1 }
|
|
- name: role
|
|
in: query
|
|
schema: { type: string }
|
|
- name: status
|
|
in: query
|
|
schema: { type: string }
|
|
responses:
|
|
'200':
|
|
description: List of users
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
data:
|
|
type: array
|
|
items: { $ref: '#/components/schemas/User' }
|
|
meta: { $ref: '#/components/schemas/PaginationMeta' }
|
|
|
|
post:
|
|
tags: [Users]
|
|
summary: Create/invite user
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema: { $ref: '#/components/schemas/UserCreate' }
|
|
responses:
|
|
'201':
|
|
description: User created
|
|
|
|
/users/{id}:
|
|
parameters:
|
|
- name: id
|
|
in: path
|
|
required: true
|
|
schema: { type: string, format: uuid }
|
|
get:
|
|
tags: [Users]
|
|
summary: Get user
|
|
responses:
|
|
'200':
|
|
description: User details
|
|
content:
|
|
application/json:
|
|
schema: { $ref: '#/components/schemas/User' }
|
|
patch:
|
|
tags: [Users]
|
|
summary: Update user
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema: { $ref: '#/components/schemas/UserUpdate' }
|
|
responses:
|
|
'200':
|
|
description: User updated
|
|
delete:
|
|
tags: [Users]
|
|
summary: Delete user
|
|
responses:
|
|
'204':
|
|
description: User deleted
|
|
|
|
/users/{id}/roles:
|
|
parameters:
|
|
- name: id
|
|
in: path
|
|
required: true
|
|
schema: { type: string, format: uuid }
|
|
post:
|
|
tags: [Users]
|
|
summary: Assign role to user
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
required: [role_id]
|
|
properties:
|
|
role_id: { type: string, format: uuid }
|
|
responses:
|
|
'200':
|
|
description: Role assigned
|
|
|
|
# Roles
|
|
/roles:
|
|
get:
|
|
tags: [Roles]
|
|
summary: List roles
|
|
responses:
|
|
'200':
|
|
description: List of roles
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
data:
|
|
type: array
|
|
items: { $ref: '#/components/schemas/Role' }
|
|
post:
|
|
tags: [Roles]
|
|
summary: Create role
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema: { $ref: '#/components/schemas/RoleCreate' }
|
|
responses:
|
|
'201':
|
|
description: Role created
|
|
|
|
# API Keys
|
|
/api-keys:
|
|
get:
|
|
tags: [API Keys]
|
|
summary: List API keys
|
|
responses:
|
|
'200':
|
|
description: List of API keys
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
data:
|
|
type: array
|
|
items: { $ref: '#/components/schemas/ApiKey' }
|
|
post:
|
|
tags: [API Keys]
|
|
summary: Generate API key
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema: { $ref: '#/components/schemas/ApiKeyCreate' }
|
|
responses:
|
|
'201':
|
|
description: API key generated (key shown once)
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
id: { type: string, format: uuid }
|
|
name: { type: string }
|
|
key: { type: string } # Shown only once!
|
|
prefix: { type: string }
|
|
scopes: { type: array, items: { type: string } }
|
|
created_at: { type: string, format: date-time }
|
|
|
|
/api-keys/{id}/revoke:
|
|
parameters:
|
|
- name: id
|
|
in: path
|
|
required: true
|
|
schema: { type: string, format: uuid }
|
|
post:
|
|
tags: [API Keys]
|
|
summary: Revoke API key
|
|
responses:
|
|
'200':
|
|
description: Key revoked
|
|
|
|
# Billing
|
|
/billing/plans:
|
|
get:
|
|
tags: [Billing]
|
|
summary: List subscription plans
|
|
responses:
|
|
'200':
|
|
description: Available plans
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
data:
|
|
type: array
|
|
items: { $ref: '#/components/schemas/SubscriptionPlan' }
|
|
|
|
/billing/subscription:
|
|
get:
|
|
tags: [Billing]
|
|
summary: Get current subscription
|
|
responses:
|
|
'200':
|
|
description: Subscription details
|
|
content:
|
|
application/json:
|
|
schema: { $ref: '#/components/schemas/Subscription' }
|
|
|
|
/billing/invoices:
|
|
get:
|
|
tags: [Billing]
|
|
summary: List invoices
|
|
parameters:
|
|
- name: status
|
|
in: query
|
|
schema: { type: string }
|
|
responses:
|
|
'200':
|
|
description: List of invoices
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
data:
|
|
type: array
|
|
items: { $ref: '#/components/schemas/Invoice' }
|
|
meta: { $ref: '#/components/schemas/PaginationMeta' }
|
|
|
|
# Audit Logs
|
|
/audit-logs:
|
|
get:
|
|
tags: [Audit Logs]
|
|
summary: List audit logs
|
|
parameters:
|
|
- name: action
|
|
in: query
|
|
schema: { type: string }
|
|
- name: user_id
|
|
in: query
|
|
schema: { type: string, format: uuid }
|
|
- name: resource_type
|
|
in: query
|
|
schema: { type: string }
|
|
- name: from
|
|
in: query
|
|
schema: { type: string, format: date-time }
|
|
- name: to
|
|
in: query
|
|
schema: { type: string, format: date-time }
|
|
- name: severity
|
|
in: query
|
|
schema: { type: string, enum: [info, warning, critical] }
|
|
responses:
|
|
'200':
|
|
description: Audit logs
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
data:
|
|
type: array
|
|
items: { $ref: '#/components/schemas/AuditLog' }
|
|
meta: { $ref: '#/components/schemas/PaginationMeta' }
|
|
|
|
/audit-logs/export:
|
|
get:
|
|
tags: [Audit Logs]
|
|
summary: Export audit logs
|
|
parameters:
|
|
- name: format
|
|
in: query
|
|
schema: { type: string, enum: [csv, json], default: csv }
|
|
responses:
|
|
'200':
|
|
description: Exported file
|
|
content:
|
|
text/csv:
|
|
schema: { type: string }
|
|
application/json:
|
|
schema: { type: string }
|
|
|
|
# Reports
|
|
/reports:
|
|
get:
|
|
tags: [Reports]
|
|
summary: List reports
|
|
responses:
|
|
'200':
|
|
description: List of reports
|
|
post:
|
|
tags: [Reports]
|
|
summary: Create report
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema: { $ref: '#/components/schemas/ReportCreate' }
|
|
responses:
|
|
'201':
|
|
description: Report created
|
|
|
|
/reports/{id}/run:
|
|
parameters:
|
|
- name: id
|
|
in: path
|
|
required: true
|
|
schema: { type: string, format: uuid }
|
|
post:
|
|
tags: [Reports]
|
|
summary: Run report
|
|
responses:
|
|
'202':
|
|
description: Report queued
|
|
|
|
# Plugins
|
|
/plugins:
|
|
get:
|
|
tags: [Plugins]
|
|
summary: List available plugins
|
|
responses:
|
|
'200':
|
|
description: Available plugins
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
data:
|
|
type: array
|
|
items: { $ref: '#/components/schemas/Plugin' }
|
|
|
|
/plugins/installed:
|
|
get:
|
|
tags: [Plugins]
|
|
summary: List installed plugins
|
|
responses:
|
|
'200':
|
|
description: Installed plugins
|
|
|
|
/plugins/{id}/install:
|
|
parameters:
|
|
- name: id
|
|
in: path
|
|
required: true
|
|
schema: { type: string, format: uuid }
|
|
post:
|
|
tags: [Plugins]
|
|
summary: Install plugin
|
|
responses:
|
|
'200':
|
|
description: Plugin installed
|
|
|
|
# Dashboard
|
|
/dashboard/summary:
|
|
get:
|
|
tags: [Dashboard]
|
|
summary: Get dashboard summary
|
|
responses:
|
|
'200':
|
|
description: Dashboard statistics
|
|
content:
|
|
application/json:
|
|
schema: { $ref: '#/components/schemas/DashboardSummary' }
|
|
|
|
components:
|
|
securitySchemes:
|
|
BearerAuth:
|
|
type: http
|
|
scheme: bearer
|
|
bearerFormat: JWT
|
|
ApiKeyAuth:
|
|
type: apiKey
|
|
in: header
|
|
name: X-API-Key
|
|
|
|
schemas:
|
|
PaginationMeta:
|
|
type: object
|
|
properties:
|
|
page: { type: integer }
|
|
per_page: { type: integer }
|
|
total: { type: integer }
|
|
total_pages: { type: integer }
|
|
|
|
Tenant:
|
|
type: object
|
|
properties:
|
|
id: { type: string, format: uuid }
|
|
name: { type: string }
|
|
slug: { type: string }
|
|
type: { type: string, enum: [municipality, enterprise, partner] }
|
|
org_number: { type: string }
|
|
billing_email: { type: string, format: email }
|
|
plan_id: { type: string, format: uuid }
|
|
status: { type: string }
|
|
settings: { type: object }
|
|
created_at: { type: string, format: date-time }
|
|
updated_at: { type: string, format: date-time }
|
|
|
|
TenantCreate:
|
|
type: object
|
|
required: [name, slug, type, billing_email]
|
|
properties:
|
|
name: { type: string, minLength: 2, maxLength: 255 }
|
|
slug: { type: string, pattern: '^[a-z0-9-]+$' }
|
|
type: { type: string, enum: [municipality, enterprise, partner] }
|
|
org_number: { type: string }
|
|
billing_email: { type: string, format: email }
|
|
plan_id: { type: string, format: uuid }
|
|
|
|
TenantUpdate:
|
|
type: object
|
|
properties:
|
|
name: { type: string }
|
|
billing_email: { type: string, format: email }
|
|
status: { type: string }
|
|
settings: { type: object }
|
|
|
|
User:
|
|
type: object
|
|
properties:
|
|
id: { type: string, format: uuid }
|
|
tenant_id: { type: string, format: uuid }
|
|
email: { type: string, format: email }
|
|
first_name: { type: string }
|
|
last_name: { type: string }
|
|
phone: { type: string }
|
|
avatar_url: { type: string }
|
|
status: { type: string }
|
|
roles: { type: array, items: { $ref: '#/components/schemas/Role' } }
|
|
last_login_at: { type: string, format: date-time }
|
|
created_at: { type: string, format: date-time }
|
|
|
|
UserCreate:
|
|
type: object
|
|
required: [email, first_name, last_name]
|
|
properties:
|
|
email: { type: string, format: email }
|
|
first_name: { type: string }
|
|
last_name: { type: string }
|
|
phone: { type: string }
|
|
role_ids: { type: array, items: { type: string, format: uuid } }
|
|
send_invite: { type: boolean, default: true }
|
|
|
|
UserUpdate:
|
|
type: object
|
|
properties:
|
|
first_name: { type: string }
|
|
last_name: { type: string }
|
|
phone: { type: string }
|
|
status: { type: string }
|
|
role_ids: { type: array, items: { type: string, format: uuid } }
|
|
|
|
Role:
|
|
type: object
|
|
properties:
|
|
id: { type: string, format: uuid }
|
|
name: { type: string }
|
|
slug: { type: string }
|
|
description: { type: string }
|
|
permissions: { type: array, items: { type: string } }
|
|
is_system: { type: boolean }
|
|
member_count: { type: integer }
|
|
created_at: { type: string, format: date-time }
|
|
|
|
RoleCreate:
|
|
type: object
|
|
required: [name, slug, permissions]
|
|
properties:
|
|
name: { type: string }
|
|
slug: { type: string }
|
|
description: { type: string }
|
|
permissions: { type: array, items: { type: string } }
|
|
|
|
ApiKey:
|
|
type: object
|
|
properties:
|
|
id: { type: string, format: uuid }
|
|
name: { type: string }
|
|
prefix: { type: string }
|
|
scopes: { type: array, items: { type: string } }
|
|
rate_limit: { type: integer }
|
|
expires_at: { type: string, format: date-time }
|
|
last_used_at: { type: string, format: date-time }
|
|
status: { type: string }
|
|
created_at: { type: string, format: date-time }
|
|
|
|
ApiKeyCreate:
|
|
type: object
|
|
required: [name]
|
|
properties:
|
|
name: { type: string }
|
|
scopes: { type: array, items: { type: string } }
|
|
rate_limit: { type: integer, default: 1000 }
|
|
expires_at: { type: string, format: date-time }
|
|
|
|
SubscriptionPlan:
|
|
type: object
|
|
properties:
|
|
id: { type: string, format: uuid }
|
|
name: { type: string }
|
|
slug: { type: string }
|
|
description: { type: string }
|
|
price_monthly: { type: number }
|
|
price_yearly: { type: number }
|
|
features: { type: object }
|
|
limits: { type: object }
|
|
|
|
Subscription:
|
|
type: object
|
|
properties:
|
|
plan: { $ref: '#/components/schemas/SubscriptionPlan' }
|
|
status: { type: string }
|
|
current_period_start: { type: string, format: date-time }
|
|
current_period_end: { type: string, format: date-time }
|
|
cancel_at_period_end: { type: boolean }
|
|
|
|
Invoice:
|
|
type: object
|
|
properties:
|
|
id: { type: string, format: uuid }
|
|
invoice_number: { type: string }
|
|
period_start: { type: string, format: date }
|
|
period_end: { type: string, format: date }
|
|
amount: { type: number }
|
|
tax_amount: { type: number }
|
|
total_amount: { type: number }
|
|
currency: { type: string, default: SEK }
|
|
status: { type: string }
|
|
due_date: { type: string, format: date }
|
|
pdf_url: { type: string }
|
|
created_at: { type: string, format: date-time }
|
|
|
|
AuditLog:
|
|
type: object
|
|
properties:
|
|
id: { type: string, format: uuid }
|
|
action: { type: string }
|
|
resource_type: { type: string }
|
|
resource_id: { type: string, format: uuid }
|
|
user: { type: object, properties: { id: { type: string }, email: { type: string } } }
|
|
details: { type: object }
|
|
ip_address: { type: string }
|
|
severity: { type: string }
|
|
created_at: { type: string, format: date-time }
|
|
|
|
ReportCreate:
|
|
type: object
|
|
required: [name, type]
|
|
properties:
|
|
name: { type: string }
|
|
type: { type: string }
|
|
config: { type: object }
|
|
schedule: { type: string }
|
|
|
|
Plugin:
|
|
type: object
|
|
properties:
|
|
id: { type: string, format: uuid }
|
|
name: { type: string }
|
|
slug: { type: string }
|
|
description: { type: string }
|
|
version: { type: string }
|
|
author: { type: string }
|
|
is_installed: { type: boolean }
|
|
is_system: { type: boolean }
|
|
|
|
DashboardSummary:
|
|
type: object
|
|
properties:
|
|
tenants:
|
|
type: object
|
|
properties:
|
|
total: { type: integer }
|
|
active: { type: integer }
|
|
trial: { type: integer }
|
|
users:
|
|
type: object
|
|
properties:
|
|
total: { type: integer }
|
|
active: { type: integer }
|
|
api_usage:
|
|
type: object
|
|
properties:
|
|
today: { type: integer }
|
|
this_month: { type: integer }
|
|
limit: { type: integer }
|
|
revenue:
|
|
type: object
|
|
properties:
|
|
mrr: { type: number }
|
|
this_month: { type: number }
|
|
last_month: { type: number }
|