veza/veza-backend-api/openapi.yaml
senke b8eed72f96 feat(webrtc): coturn ICE config endpoint + frontend wiring + ops template (v1.0.9 item 1.2)
Closes FUNCTIONAL_AUDIT.md §4 #1: WebRTC 1:1 calls had working
signaling but no NAT traversal, so calls between two peers behind
symmetric NAT (corporate firewalls, mobile carrier CGNAT, Incus
container default networking) failed silently after the SDP exchange.

Backend:
  - GET /api/v1/config/webrtc (public) returns {iceServers: [...]}
    built from WEBRTC_STUN_URLS / WEBRTC_TURN_URLS / *_USERNAME /
    *_CREDENTIAL env vars. Half-config (URLs without creds, or vice
    versa) deliberately omits the TURN block — a half-configured TURN
    surfaces auth errors at call time instead of falling back cleanly
    to STUN-only.
  - 4 handler tests cover the matrix.

Frontend:
  - services/api/webrtcConfig.ts caches the config for the page
    lifetime and falls back to the historical hardcoded Google STUN
    if the fetch fails.
  - useWebRTC fetches at mount, hands iceServers synchronously to
    every RTCPeerConnection, exposes a {hasTurn, loaded} hint.
  - CallButton tooltip warns up-front when TURN isn't configured
    instead of letting calls time out silently.

Ops:
  - infra/coturn/turnserver.conf — annotated template with the SSRF-
    safe denied-peer-ip ranges, prometheus exporter, TLS for TURNS,
    static lt-cred-mech (REST-secret rotation deferred to v1.1).
  - infra/coturn/README.md — Incus deploy walkthrough, smoke test
    via turnutils_uclient, capacity rules of thumb.
  - docs/ENV_VARIABLES.md gains a 13bis. WebRTC ICE servers section.

Coturn deployment itself is a separate ops action — this commit lands
the plumbing so the deploy can light up the path with zero code
changes.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-26 23:38:42 +02:00

6636 lines
183 KiB
YAML

basePath: /api/v1
definitions:
internal_core_track.BatchDeleteRequest:
properties:
track_ids:
items:
type: string
minItems: 1
type: array
required:
- track_ids
type: object
internal_core_track.BatchUpdateRequest:
properties:
track_ids:
items:
type: string
minItems: 1
type: array
updates:
additionalProperties: true
type: object
required:
- track_ids
- updates
type: object
internal_core_track.CompleteChunkedUploadRequest:
properties:
upload_id:
type: string
required:
- upload_id
type: object
internal_core_track.CreateShareRequest:
properties:
expires_at:
type: string
permissions:
enum:
- read
- write
- admin
type: string
required:
- permissions
type: object
internal_core_track.InitiateChunkedUploadRequest:
properties:
filename:
type: string
total_chunks:
minimum: 1
type: integer
total_size:
minimum: 1
type: integer
required:
- filename
- total_chunks
- total_size
type: object
internal_core_track.RecordPlayRequest:
properties:
play_time:
minimum: 0
type: integer
type: object
internal_core_track.StreamCallbackRequest:
properties:
error:
type: string
manifest_url:
type: string
status:
enum:
- completed
- failed
- processing
type: string
required:
- status
type: object
internal_core_track.UpdateLyricsRequest:
properties:
content:
type: string
type: object
internal_core_track.UpdateTrackRequest:
properties:
album:
maxLength: 255
type: string
artist:
maxLength: 255
type: string
bpm:
maximum: 300
minimum: 0
type: integer
genre:
description: legacy, single
maxLength: 100
type: string
genres:
description: 'v0.10.1: max 3, taxonomy slugs'
items:
type: string
type: array
is_public:
type: boolean
musical_key:
maxLength: 10
type: string
tags:
description: 'v0.10.1: max 10, 30 chars each'
items:
type: string
type: array
title:
maxLength: 255
minLength: 1
type: string
year:
maximum: 2100
minimum: 1900
type: integer
type: object
internal_handlers.APIResponse:
properties:
data: {}
error: {}
success:
type: boolean
type: object
internal_handlers.AddCollaboratorRequest:
properties:
permission:
enum:
- read
- write
- admin
type: string
user_id:
type: string
required:
- permission
- user_id
type: object
internal_handlers.AddQueueItemRequest:
properties:
track_id:
type: string
required:
- track_id
type: object
internal_handlers.AddToSessionRequest:
properties:
track_id:
type: string
required:
- track_id
type: object
internal_handlers.CreateCommentRequest:
properties:
content:
maxLength: 5000
minLength: 1
type: string
parent_id:
type: string
timestamp:
description: Position in seconds (0 = top-level, no specific time)
type: number
required:
- content
type: object
internal_handlers.CreateOrderRequest:
properties:
items:
items:
properties:
product_id:
type: string
required:
- product_id
type: object
minItems: 1
type: array
promo_code:
maxLength: 50
type: string
required:
- items
type: object
internal_handlers.CreatePlaylistRequest:
properties:
description:
maxLength: 1000
type: string
is_public:
type: boolean
title:
maxLength: 200
minLength: 1
type: string
required:
- title
type: object
internal_handlers.CreateProductRequest:
properties:
bpm:
description: v0.401 M1
maximum: 300
minimum: 1
type: integer
category:
enum:
- sample
- beat
- preset
- pack
type: string
description:
maxLength: 2000
type: string
license_type:
enum:
- standard
- exclusive
- commercial
type: string
licenses:
description: 'v0.401 M2: Product licenses (streaming, personal, commercial,
exclusive)'
items:
properties:
license_type:
enum:
- streaming
- personal
- commercial
- exclusive
type: string
price_cents:
minimum: 0
type: integer
terms_text:
type: string
required:
- license_type
- price_cents
type: object
type: array
musical_key:
maxLength: 10
type: string
price:
minimum: 0
type: number
product_type:
enum:
- track
- pack
- service
type: string
title:
maxLength: 200
minLength: 3
type: string
track_id:
description: UUID string
type: string
required:
- price
- product_type
- title
type: object
internal_handlers.DashboardResponse:
properties:
library_preview:
$ref: '#/definitions/internal_handlers.LibraryPreview'
recent_activity:
items:
$ref: '#/definitions/internal_handlers.RecentActivity'
type: array
stats:
$ref: '#/definitions/internal_handlers.DashboardStats'
type: object
internal_handlers.DashboardStats:
properties:
active_friends:
type: integer
active_friends_change:
type: string
favorites:
type: integer
favorites_change:
type: string
messages_sent:
type: integer
messages_sent_change:
type: string
period:
type: string
tracks_played:
type: integer
tracks_played_change:
type: string
type: object
internal_handlers.DeleteAccountRequest:
properties:
confirm_text:
type: string
keep_public_tracks:
description: If true, public tracks remain (attributed to deleted account)
type: boolean
password:
type: string
reason:
type: string
required:
- confirm_text
- password
type: object
internal_handlers.DisableTwoFactorRequest:
properties:
password:
type: string
required:
- password
type: object
internal_handlers.FrontendLogRequest:
properties:
context:
additionalProperties: true
type: object
data: {}
level:
type: string
message:
type: string
timestamp:
type: string
type: object
internal_handlers.IceServer:
properties:
credential:
type: string
urls:
items:
type: string
type: array
username:
type: string
type: object
internal_handlers.ImportPlaylistRequest:
properties:
playlist:
properties:
description:
type: string
is_public:
type: boolean
title:
type: string
type: object
tracks:
items:
properties:
id:
type: string
type: object
type: array
type: object
internal_handlers.LibraryPreview:
properties:
has_more:
type: boolean
items:
items:
$ref: '#/definitions/internal_handlers.TrackPreview'
type: array
total_count:
type: integer
type: object
internal_handlers.RecentActivity:
properties:
description:
type: string
icon:
type: string
id:
type: string
metadata:
additionalProperties: true
type: object
timestamp:
type: string
title:
type: string
type:
type: string
type: object
internal_handlers.ReorderTracksRequest:
properties:
track_ids:
description: Changed to []uuid.UUID
items:
type: string
minItems: 1
type: array
required:
- track_ids
type: object
internal_handlers.RequestPasswordResetRequest:
properties:
email:
type: string
required:
- email
type: object
internal_handlers.ResetPasswordRequest:
properties:
new_password:
minLength: 12
type: string
token:
type: string
required:
- new_password
- token
type: object
internal_handlers.SetupTwoFactorResponse:
properties:
qr_code_url:
type: string
recovery_codes:
items:
type: string
type: array
secret:
type: string
type: object
internal_handlers.StreamTokenResponse:
properties:
expires_in:
description: seconds
type: integer
token:
type: string
type: object
internal_handlers.TrackPreview:
properties:
artist:
type: string
cover_art_path:
type: string
created_at:
type: string
duration:
type: integer
id:
type: string
like_count:
type: integer
play_count:
type: integer
title:
type: string
type: object
internal_handlers.UpdateCollaboratorPermissionRequest:
properties:
permission:
enum:
- read
- write
- admin
type: string
required:
- permission
type: object
internal_handlers.UpdateCommentRequest:
properties:
content:
maxLength: 5000
minLength: 1
type: string
required:
- content
type: object
internal_handlers.UpdatePlaylistRequest:
properties:
description:
maxLength: 1000
type: string
is_public:
type: boolean
title:
maxLength: 200
minLength: 1
type: string
type: object
internal_handlers.UpdateProductRequest:
properties:
bpm:
maximum: 300
minimum: 1
type: integer
category:
enum:
- sample
- beat
- preset
- pack
type: string
description:
maxLength: 2000
type: string
licenses:
description: 'v0.401 M2: Product licenses'
items:
properties:
license_type:
enum:
- streaming
- personal
- commercial
- exclusive
type: string
price_cents:
minimum: 0
type: integer
terms_text:
type: string
required:
- license_type
- price_cents
type: object
type: array
musical_key:
maxLength: 10
type: string
price:
minimum: 0
type: number
status:
enum:
- draft
- active
- archived
type: string
title:
maxLength: 200
minLength: 3
type: string
type: object
internal_handlers.UpdateProfileRequest:
properties:
banner_url:
maxLength: 2048
type: string
bio:
maxLength: 500
type: string
birthdate:
type: string
first_name:
maxLength: 100
type: string
gender:
enum:
- Male
- Female
- Other
- Prefer not to say
type: string
is_public:
type: boolean
last_name:
maxLength: 100
type: string
location:
maxLength: 100
type: string
social_links:
additionalProperties: true
type: object
username:
maxLength: 30
minLength: 3
type: string
type: object
internal_handlers.ValidateRequest:
properties:
data:
description: The data to validate
items:
type: integer
type: array
type:
description: e.g., "RegisterRequest", "LoginRequest"
type: string
required:
- data
- type
type: object
internal_handlers.ValidateResponse:
properties:
errors:
items:
$ref: '#/definitions/veza-backend-api_internal_dto.ValidationError'
type: array
message:
type: string
valid:
type: boolean
type: object
internal_handlers.VerifyTwoFactorRequest:
properties:
code:
description: TOTP code to verify
type: string
secret:
description: Secret from setup step
type: string
required:
- code
- secret
type: object
internal_handlers.WebRTCConfigResponse:
properties:
iceServers:
items:
$ref: '#/definitions/internal_handlers.IceServer'
type: array
type: object
veza-backend-api_internal_core_marketplace.LicenseType:
enum:
- basic
- premium
- exclusive
type: string
x-enum-varnames:
- LicenseBasic
- LicensePremium
- LicenseExclusive
veza-backend-api_internal_core_marketplace.Order:
properties:
buyer_id:
type: string
created_at:
type: string
currency:
type: string
discount_amount_cents:
type: integer
hyperswitch_payment_id:
type: string
id:
type: string
items:
items:
$ref: '#/definitions/veza-backend-api_internal_core_marketplace.OrderItem'
type: array
payment_intent:
description: Legacy / Stripe PaymentIntent ID
type: string
payment_status:
description: Hyperswitch payment status
type: string
promo_code_id:
type: string
refund_deadline:
description: 'v0.12.0: 14-day refund deadline'
type: string
status:
description: pending, completed, failed, refunded
type: string
total_amount:
type: number
updated_at:
type: string
type: object
veza-backend-api_internal_core_marketplace.OrderItem:
properties:
id:
type: string
order_id:
type: string
price:
type: number
product_id:
type: string
type: object
veza-backend-api_internal_core_marketplace.Product:
properties:
avg_rating:
description: 'v0.403 R1: Computed from product_reviews (not stored in DB)'
type: number
bpm:
description: 'v0.401 M1: Métadonnées musicales et catégorie'
type: integer
category:
description: sample, beat, preset, pack
type: string
created_at:
type: string
currency:
type: string
description:
type: string
id:
type: string
images:
items:
$ref: '#/definitions/veza-backend-api_internal_core_marketplace.ProductImage'
type: array
license_type:
$ref: '#/definitions/veza-backend-api_internal_core_marketplace.LicenseType'
licenses:
items:
$ref: '#/definitions/veza-backend-api_internal_core_marketplace.ProductLicense'
type: array
musical_key:
type: string
previews:
description: Relations
items:
$ref: '#/definitions/veza-backend-api_internal_core_marketplace.ProductPreview'
type: array
price:
type: number
product_type:
description: '"track", "pack", "service"'
type: string
review_count:
type: integer
seller_id:
type: string
status:
$ref: '#/definitions/veza-backend-api_internal_core_marketplace.ProductStatus'
title:
type: string
track_id:
description: Liaison optionnelle avec un Track (si ProductType == "track")
type: string
updated_at:
type: string
type: object
veza-backend-api_internal_core_marketplace.ProductImage:
properties:
created_at:
type: string
id:
type: string
product_id:
type: string
sort_order:
type: integer
url:
type: string
type: object
veza-backend-api_internal_core_marketplace.ProductLicense:
properties:
created_at:
type: string
id:
type: string
license_type:
description: streaming, personal, commercial, exclusive
type: string
price_cents:
type: integer
product_id:
type: string
terms_text:
type: string
type: object
veza-backend-api_internal_core_marketplace.ProductPreview:
properties:
created_at:
type: string
duration_sec:
type: integer
file_path:
type: string
id:
type: string
product_id:
type: string
type: object
veza-backend-api_internal_core_marketplace.ProductStatus:
enum:
- draft
- active
- archived
type: string
x-enum-varnames:
- ProductStatusDraft
- ProductStatusActive
- ProductStatusArchived
veza-backend-api_internal_dto.LoginRequest:
properties:
email:
type: string
password:
type: string
remember_me:
type: boolean
required:
- email
- password
type: object
veza-backend-api_internal_dto.LoginResponse:
properties:
requires_2fa:
description: 'BE-API-001: Flag indicating 2FA is required'
type: boolean
token:
$ref: '#/definitions/veza-backend-api_internal_dto.TokenResponse'
user:
$ref: '#/definitions/veza-backend-api_internal_dto.UserResponse'
type: object
veza-backend-api_internal_dto.RefreshRequest:
properties:
refresh_token:
type: string
required:
- refresh_token
type: object
veza-backend-api_internal_dto.RegisterRequest:
properties:
email:
type: string
password:
minLength: 12
type: string
password_confirmation:
type: string
username:
maxLength: 50
minLength: 3
type: string
required:
- email
- password
- password_confirmation
type: object
veza-backend-api_internal_dto.RegisterResponse:
properties:
message:
type: string
user:
$ref: '#/definitions/veza-backend-api_internal_dto.UserResponse'
verification_required:
type: boolean
type: object
veza-backend-api_internal_dto.ResendVerificationRequest:
properties:
email:
type: string
required:
- email
type: object
veza-backend-api_internal_dto.TokenResponse:
properties:
access_token:
type: string
expires_in:
type: integer
refresh_token:
type: string
type: object
veza-backend-api_internal_dto.UserResponse:
properties:
email:
type: string
id:
type: string
username:
type: string
type: object
veza-backend-api_internal_dto.ValidationError:
properties:
field:
type: string
message:
type: string
value:
type: string
type: object
veza-backend-api_internal_handlers.APIResponse:
properties:
data: {}
error: {}
success:
type: boolean
type: object
veza-backend-api_internal_models.Playlist:
properties:
collaborators:
items:
$ref: '#/definitions/veza-backend-api_internal_models.PlaylistCollaborator'
type: array
cover_url:
type: string
created_at:
type: string
description:
type: string
follower_count:
type: integer
id:
type: string
is_default_favorites:
description: v0.10.4 F136
type: boolean
is_editorial:
description: v0.10.4 F141
type: boolean
is_public:
type: boolean
title:
type: string
track_count:
type: integer
tracks:
items:
$ref: '#/definitions/veza-backend-api_internal_models.PlaylistTrack'
type: array
updated_at:
type: string
user_id:
type: string
type: object
veza-backend-api_internal_models.PlaylistCollaborator:
properties:
created_at:
type: string
id:
type: string
permission:
$ref: '#/definitions/veza-backend-api_internal_models.PlaylistPermission'
playlist_id:
type: string
updated_at:
type: string
user:
$ref: '#/definitions/veza-backend-api_internal_models.User'
user_id:
type: string
type: object
veza-backend-api_internal_models.PlaylistPermission:
enum:
- read
- write
- admin
type: string
x-enum-varnames:
- PlaylistPermissionRead
- PlaylistPermissionWrite
- PlaylistPermissionAdmin
veza-backend-api_internal_models.PlaylistTrack:
properties:
added_at:
type: string
added_by:
type: string
id:
type: string
playlist_id:
type: string
position:
type: integer
track:
$ref: '#/definitions/veza-backend-api_internal_models.Track'
track_id:
type: string
type: object
veza-backend-api_internal_models.Track:
properties:
album:
type: string
artist:
type: string
bitrate:
description: kbps
type: integer
bpm:
type: integer
cover_art_path:
type: string
created_at:
type: string
creator_id:
type: string
duration:
description: seconds
type: integer
file_id:
description: NULL temporairement avant création fichier
type: string
file_path:
type: string
file_size:
description: bytes
type: integer
format:
description: mp3, flac, wav, etc.
type: string
genre:
type: string
id:
type: string
is_public:
type: boolean
musical_key:
type: string
sample_rate:
description: Hz
type: integer
status:
$ref: '#/definitions/veza-backend-api_internal_models.TrackStatus'
status_message:
type: string
stream_manifest_url:
type: string
stream_status:
description: pending, processing, ready, error
type: string
tags:
items:
type: string
type: array
title:
type: string
updated_at:
type: string
waveform_path:
type: string
waveform_url:
type: string
year:
type: integer
type: object
veza-backend-api_internal_models.TrackStatus:
enum:
- uploading
- processing
- completed
- failed
type: string
x-enum-varnames:
- TrackStatusUploading
- TrackStatusProcessing
- TrackStatusCompleted
- TrackStatusFailed
veza-backend-api_internal_models.User:
properties:
avatar:
type: string
banner_url:
type: string
bio:
type: string
birthdate:
type: string
created_at:
type: string
email:
type: string
first_name:
type: string
gender:
type: string
id:
type: string
is_active:
type: boolean
is_admin:
type: boolean
is_banned:
type: boolean
is_public:
type: boolean
is_verified:
type: boolean
last_login_at:
type: string
last_name:
type: string
location:
type: string
login_count:
type: integer
password:
description: Virtual field for input
type: string
password_changed_at:
description: 'F016: Password expiration tracking'
type: string
promoted_to_creator_at:
description: |-
v1.0.6: set the first time a user self-promotes to `role='creator'`
via POST /api/v1/users/me/upgrade-creator. NULL for users who never
took that path (still 'user', or promoted by an admin out-of-band).
type: string
role:
type: string
slug:
type: string
social_links:
type: string
token_version:
type: integer
updated_at:
type: string
username:
type: string
username_changed_at:
type: string
type: object
veza-backend-api_internal_response.APIResponse:
properties:
data: {}
error: {}
success:
type: boolean
type: object
veza-backend-api_internal_services.UpdateQueueRequest:
properties:
current_position:
type: integer
current_track_id:
type: string
is_playing:
type: boolean
item_order:
items:
type: string
type: array
repeat_mode:
type: string
shuffle:
type: boolean
volume:
type: integer
type: object
host: localhost:18080
info:
contact:
email: support@veza.app
name: API Support
url: http://www.veza.app/support
description: Backend API for Veza platform.
license:
name: Apache 2.0
url: http://www.apache.org/licenses/LICENSE-2.0.html
termsOfService: http://swagger.io/terms/
title: Veza Backend API
version: 1.2.0
paths:
/api/v1/dashboard:
get:
consumes:
- application/json
description: Get aggregated dashboard data including stats, recent activity,
and library preview
parameters:
- description: 'Number of recent activity items (default: 10)'
in: query
name: activity_limit
type: integer
- description: 'Number of library items (default: 5)'
in: query
name: library_limit
type: integer
- description: 'Time period for statistics: 7d, 30d, 90d, all (default: 30d)'
in: query
name: stats_period
type: string
produces:
- application/json
responses:
"200":
description: OK
schema:
allOf:
- $ref: '#/definitions/internal_handlers.APIResponse'
- properties:
data:
$ref: '#/definitions/internal_handlers.DashboardResponse'
type: object
"401":
description: Unauthorized
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
"500":
description: Internal server error
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
security:
- BearerAuth: []
summary: Get Dashboard Data
tags:
- Dashboard
/api/v1/logs/frontend:
post:
consumes:
- application/json
description: Receive and store a log entry from the frontend application
parameters:
- description: Frontend log entry
in: body
name: log
required: true
schema:
$ref: '#/definitions/internal_handlers.FrontendLogRequest'
produces:
- application/json
responses:
"200":
description: OK
schema:
allOf:
- $ref: '#/definitions/internal_handlers.APIResponse'
- properties:
data:
properties:
received:
type: boolean
type: object
type: object
"400":
description: Invalid log entry
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
"500":
description: Internal server error
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
summary: Receive frontend log
tags:
- Logging
/api/v1/marketplace/download/{product_id}:
get:
consumes:
- application/json
description: Get a secure download URL for a purchased product
parameters:
- description: Product ID
in: path
name: product_id
required: true
type: string
produces:
- application/json
responses:
"200":
description: OK
schema:
additionalProperties:
type: string
type: object
"403":
description: No license
schema:
$ref: '#/definitions/veza-backend-api_internal_response.APIResponse'
"404":
description: Not Found
schema:
$ref: '#/definitions/veza-backend-api_internal_response.APIResponse'
security:
- BearerAuth: []
summary: Get download URL
tags:
- Marketplace
/api/v1/marketplace/orders:
get:
consumes:
- application/json
description: Get all orders for the authenticated user
produces:
- application/json
responses:
"200":
description: OK
schema:
items:
$ref: '#/definitions/veza-backend-api_internal_core_marketplace.Order'
type: array
"401":
description: Unauthorized
schema:
$ref: '#/definitions/veza-backend-api_internal_response.APIResponse'
"500":
description: Internal Error
schema:
$ref: '#/definitions/veza-backend-api_internal_response.APIResponse'
security:
- BearerAuth: []
summary: List user orders
tags:
- Marketplace
post:
consumes:
- application/json
description: Purchase products
parameters:
- description: Order items
in: body
name: order
required: true
schema:
$ref: '#/definitions/internal_handlers.CreateOrderRequest'
produces:
- application/json
responses:
"201":
description: Created
schema:
$ref: '#/definitions/veza-backend-api_internal_core_marketplace.Order'
"400":
description: Validation Error
schema:
$ref: '#/definitions/veza-backend-api_internal_response.APIResponse'
"401":
description: Unauthorized
schema:
$ref: '#/definitions/veza-backend-api_internal_response.APIResponse'
security:
- BearerAuth: []
summary: Create a new order
tags:
- Marketplace
/api/v1/marketplace/orders/{id}:
get:
consumes:
- application/json
description: Get details of a specific order (only order owner can access)
parameters:
- description: Order ID
in: path
name: id
required: true
type: string
produces:
- application/json
responses:
"200":
description: OK
schema:
$ref: '#/definitions/veza-backend-api_internal_core_marketplace.Order'
"400":
description: Validation Error
schema:
$ref: '#/definitions/veza-backend-api_internal_response.APIResponse'
"401":
description: Unauthorized
schema:
$ref: '#/definitions/veza-backend-api_internal_response.APIResponse'
"403":
description: Forbidden - Not order owner
schema:
$ref: '#/definitions/veza-backend-api_internal_response.APIResponse'
"404":
description: Order not found
schema:
$ref: '#/definitions/veza-backend-api_internal_response.APIResponse'
security:
- BearerAuth: []
summary: Get order details
tags:
- Marketplace
/api/v1/marketplace/products:
get:
consumes:
- application/json
description: List marketplace products with filters
parameters:
- description: Product status
in: query
name: status
type: string
- description: Seller ID
in: query
name: seller_id
type: string
- description: Search query
in: query
name: q
type: string
- description: Product type (track, pack, service)
in: query
name: type
type: string
- description: Minimum price
in: query
name: min_price
type: number
- description: Maximum price
in: query
name: max_price
type: number
- description: Page number
in: query
name: page
type: integer
- description: Items per page
in: query
name: limit
type: integer
produces:
- application/json
responses:
"200":
description: OK
schema:
items:
$ref: '#/definitions/veza-backend-api_internal_core_marketplace.Product'
type: array
summary: List products
tags:
- Marketplace
post:
consumes:
- application/json
description: Create a product (Track, Pack, Service) for sale
parameters:
- description: Product info
in: body
name: product
required: true
schema:
$ref: '#/definitions/internal_handlers.CreateProductRequest'
produces:
- application/json
responses:
"201":
description: Created
schema:
$ref: '#/definitions/veza-backend-api_internal_core_marketplace.Product'
"400":
description: Validation Error
schema:
$ref: '#/definitions/veza-backend-api_internal_response.APIResponse'
"401":
description: Unauthorized
schema:
$ref: '#/definitions/veza-backend-api_internal_response.APIResponse'
security:
- BearerAuth: []
summary: Create a new product
tags:
- Marketplace
/api/v1/marketplace/products/{id}:
put:
consumes:
- application/json
description: Update product details (only seller can update)
parameters:
- description: Product ID
in: path
name: id
required: true
type: string
- description: Product updates
in: body
name: product
required: true
schema:
$ref: '#/definitions/internal_handlers.UpdateProductRequest'
produces:
- application/json
responses:
"200":
description: OK
schema:
$ref: '#/definitions/veza-backend-api_internal_core_marketplace.Product'
"400":
description: Validation Error
schema:
$ref: '#/definitions/veza-backend-api_internal_response.APIResponse'
"401":
description: Unauthorized
schema:
$ref: '#/definitions/veza-backend-api_internal_response.APIResponse'
"403":
description: Forbidden - Not product owner
schema:
$ref: '#/definitions/veza-backend-api_internal_response.APIResponse'
"404":
description: Product not found
schema:
$ref: '#/definitions/veza-backend-api_internal_response.APIResponse'
security:
- BearerAuth: []
summary: Update a product
tags:
- Marketplace
/audit/activity:
get:
consumes:
- application/json
description: Get recent activity logs for the current user
parameters:
- default: 50
description: Number of activities to return
in: query
name: limit
type: integer
produces:
- application/json
responses:
"200":
description: OK
schema:
allOf:
- $ref: '#/definitions/internal_handlers.APIResponse'
- properties:
data:
properties:
activities:
type: array
type: object
type: object
"401":
description: Unauthorized
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
"500":
description: Internal server error
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
security:
- BearerAuth: []
summary: Get user activity
tags:
- Audit
/audit/logs:
get:
consumes:
- application/json
description: Search and filter audit logs with pagination support. Supports
filtering by action, resource, date range, IP address, and user agent.
parameters:
- description: Filter by action type
in: query
name: action
type: string
- description: Filter by resource type
in: query
name: resource
type: string
- description: Filter by resource ID (UUID)
in: query
name: resource_id
type: string
- description: Filter by IP address
in: query
name: ip_address
type: string
- description: Filter by user agent
in: query
name: user_agent
type: string
- description: Start date filter (YYYY-MM-DD)
in: query
name: start_date
type: string
- description: End date filter (YYYY-MM-DD)
in: query
name: end_date
type: string
- default: 1
description: Page number
in: query
name: page
type: integer
- default: 20
description: Items per page
in: query
name: limit
type: integer
- description: Offset for pagination
in: query
name: offset
type: integer
produces:
- application/json
responses:
"200":
description: OK
schema:
allOf:
- $ref: '#/definitions/internal_handlers.APIResponse'
- properties:
data:
properties:
logs:
type: array
pagination:
type: object
type: object
type: object
"400":
description: Validation error
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
"401":
description: Unauthorized
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
"500":
description: Internal server error
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
security:
- BearerAuth: []
summary: Search audit logs
tags:
- Audit
/audit/stats:
get:
consumes:
- application/json
description: Get audit statistics for the current user, optionally filtered
by date range
parameters:
- description: Start date (YYYY-MM-DD)
in: query
name: start_date
type: string
- description: End date (YYYY-MM-DD)
in: query
name: end_date
type: string
produces:
- application/json
responses:
"200":
description: OK
schema:
allOf:
- $ref: '#/definitions/internal_handlers.APIResponse'
- properties:
data:
properties:
stats:
type: object
type: object
type: object
"400":
description: Validation error
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
"401":
description: Unauthorized
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
"500":
description: Internal server error
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
security:
- BearerAuth: []
summary: Get audit statistics
tags:
- Audit
/auth/2fa/disable:
post:
consumes:
- application/json
description: Disable 2FA for user (requires password confirmation)
parameters:
- description: Password Confirmation
in: body
name: request
required: true
schema:
$ref: '#/definitions/internal_handlers.DisableTwoFactorRequest'
produces:
- application/json
responses:
"200":
description: OK
schema:
allOf:
- $ref: '#/definitions/internal_handlers.APIResponse'
- properties:
data:
properties:
message:
type: string
type: object
type: object
"400":
description: Invalid password or 2FA not enabled
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
"401":
description: Unauthorized
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
"500":
description: Internal Error
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
security:
- BearerAuth: []
summary: Disable 2FA
tags:
- Auth
/auth/2fa/setup:
post:
consumes:
- application/json
description: Generate 2FA secret and QR code for setup
produces:
- application/json
responses:
"200":
description: OK
schema:
allOf:
- $ref: '#/definitions/internal_handlers.APIResponse'
- properties:
data:
$ref: '#/definitions/internal_handlers.SetupTwoFactorResponse'
type: object
"400":
description: 2FA already enabled
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
"401":
description: Unauthorized
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
"500":
description: Internal Error
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
security:
- BearerAuth: []
summary: Setup 2FA
tags:
- Auth
/auth/2fa/status:
get:
consumes:
- application/json
description: Get 2FA enabled status for authenticated user
produces:
- application/json
responses:
"200":
description: OK
schema:
allOf:
- $ref: '#/definitions/internal_handlers.APIResponse'
- properties:
data:
properties:
enabled:
type: boolean
type: object
type: object
"401":
description: Unauthorized
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
"500":
description: Internal Error
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
security:
- BearerAuth: []
summary: Get 2FA Status
tags:
- Auth
/auth/2fa/verify:
post:
consumes:
- application/json
description: Verify 2FA code and enable 2FA for user
parameters:
- description: 2FA Code
in: body
name: request
required: true
schema:
$ref: '#/definitions/internal_handlers.VerifyTwoFactorRequest'
produces:
- application/json
responses:
"200":
description: OK
schema:
allOf:
- $ref: '#/definitions/internal_handlers.APIResponse'
- properties:
data:
properties:
message:
type: string
type: object
type: object
"400":
description: Invalid code
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
"401":
description: Unauthorized
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
"500":
description: Internal Error
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
security:
- BearerAuth: []
summary: Verify and Enable 2FA
tags:
- Auth
/auth/check-username:
get:
consumes:
- application/json
description: Check if a username is already taken
parameters:
- description: Username to check
in: query
name: username
required: true
type: string
produces:
- application/json
responses:
"200":
description: OK
schema:
allOf:
- $ref: '#/definitions/internal_handlers.APIResponse'
- properties:
data:
properties:
available:
type: boolean
username:
type: string
type: object
type: object
"400":
description: Missing Username
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
summary: Check Username Availability
tags:
- Auth
/auth/login:
post:
consumes:
- application/json
description: Authenticate user and return access token. Refresh token is set
in httpOnly cookie.
parameters:
- description: Login Credentials
in: body
name: request
required: true
schema:
$ref: '#/definitions/veza-backend-api_internal_dto.LoginRequest'
produces:
- application/json
responses:
"200":
description: Access token returned in body, refresh token in httpOnly cookie
schema:
$ref: '#/definitions/veza-backend-api_internal_dto.LoginResponse'
"400":
description: Validation or Bad Request
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
"401":
description: Invalid credentials
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
"500":
description: Internal Error
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
summary: User Login
tags:
- Auth
/auth/logout:
post:
consumes:
- application/json
description: Revoke refresh token and current session
parameters:
- description: Refresh Token to revoke
in: body
name: request
required: true
schema:
properties:
refresh_token:
type: string
type: object
produces:
- application/json
responses:
"200":
description: Success message
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
"400":
description: Validation Error
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
"401":
description: Unauthorized
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
security:
- BearerAuth: []
summary: Logout
tags:
- Auth
/auth/me:
get:
consumes:
- application/json
description: Get profile information of the currently logged-in user
produces:
- application/json
responses:
"200":
description: OK
schema:
allOf:
- $ref: '#/definitions/internal_handlers.APIResponse'
- properties:
data:
type: object
type: object
"401":
description: Unauthorized
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
"404":
description: User not found
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
security:
- BearerAuth: []
summary: Get Current User
tags:
- Auth
/auth/password/reset:
post:
consumes:
- application/json
description: Completes a password reset using a valid token previously emailed
to the user. Invalidates all the user's existing sessions on success.
parameters:
- description: Reset token + new password
in: body
name: request
required: true
schema:
$ref: '#/definitions/internal_handlers.ResetPasswordRequest'
produces:
- application/json
responses:
"200":
description: Password reset successfully
schema:
allOf:
- $ref: '#/definitions/internal_handlers.APIResponse'
- properties:
data:
properties:
message:
type: string
type: object
type: object
"400":
description: Invalid or expired token, or password validation failed
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
"500":
description: Failed to update password
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
summary: Reset password with token
tags:
- Auth
/auth/password/reset-request:
post:
consumes:
- application/json
description: Sends a password reset link to the user's email if the address
exists. Always returns 200 with a generic message to prevent email enumeration.
parameters:
- description: Email of the account to reset
in: body
name: request
required: true
schema:
$ref: '#/definitions/internal_handlers.RequestPasswordResetRequest'
produces:
- application/json
responses:
"200":
description: If the email exists, a reset link has been sent
schema:
allOf:
- $ref: '#/definitions/internal_handlers.APIResponse'
- properties:
data:
properties:
message:
type: string
type: object
type: object
"400":
description: Validation error
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
"500":
description: Token generation/storage failed (or SMTP failure in production)
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
summary: Request password reset
tags:
- Auth
/auth/refresh:
post:
consumes:
- application/json
description: Get a new access token using a refresh token
parameters:
- description: Refresh Token
in: body
name: request
required: true
schema:
$ref: '#/definitions/veza-backend-api_internal_dto.RefreshRequest'
produces:
- application/json
responses:
"200":
description: OK
schema:
$ref: '#/definitions/veza-backend-api_internal_dto.TokenResponse'
"400":
description: Validation Error
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
"401":
description: Invalid/Expired Refresh Token
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
"500":
description: Internal Error
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
summary: Refresh Token
tags:
- Auth
/auth/register:
post:
consumes:
- application/json
description: Register a new user account
parameters:
- description: Registration Data
in: body
name: request
required: true
schema:
$ref: '#/definitions/veza-backend-api_internal_dto.RegisterRequest'
produces:
- application/json
responses:
"201":
description: Created
schema:
$ref: '#/definitions/veza-backend-api_internal_dto.RegisterResponse'
"400":
description: Validation Error
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
"409":
description: User already exists
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
"500":
description: Internal Error
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
summary: User Registration
tags:
- Auth
/auth/resend-verification:
post:
consumes:
- application/json
description: Resend the email verification link
parameters:
- description: Email
in: body
name: request
required: true
schema:
$ref: '#/definitions/veza-backend-api_internal_dto.ResendVerificationRequest'
produces:
- application/json
responses:
"200":
description: Success message
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
"400":
description: Validation Error
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
summary: Resend Verification Email
tags:
- Auth
/auth/stream-token:
post:
description: Returns a 5-minute JWT for HLS and WebSocket authentication (httpOnly
cookies prevent direct token access)
responses:
"200":
description: OK
schema:
$ref: '#/definitions/internal_handlers.StreamTokenResponse'
"401":
description: Unauthorized
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
security:
- BearerAuth: []
summary: Get ephemeral stream token
tags:
- Auth
/auth/verify-email:
post:
consumes:
- application/json
description: |-
Verify user email address using a token. v1.0.9 item 1.3:
the token is read from the X-Verify-Token header (anti-leak
via Referer / proxy access logs). The query-param form
remains accepted for backward compatibility with emails sent
before v1.0.9 — both paths log a deprecation warning when
the query path is used.
parameters:
- description: Verification Token (preferred)
in: header
name: X-Verify-Token
required: true
type: string
- description: Verification Token (deprecated, accepted for backward compat)
in: query
name: token
type: string
produces:
- application/json
responses:
"200":
description: Success message
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
"400":
description: Invalid Token
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
summary: Verify Email
tags:
- Auth
/chat/token:
get:
consumes:
- application/json
description: Generate a short-lived token for chat authentication
produces:
- application/json
responses:
"200":
description: OK
schema:
allOf:
- $ref: '#/definitions/internal_handlers.APIResponse'
- properties:
data:
properties:
token:
type: string
type: object
type: object
"401":
description: Unauthorized
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
"500":
description: Internal Error
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
security:
- BearerAuth: []
summary: Get Chat Token
tags:
- Chat
/comments/{id}:
put:
consumes:
- application/json
description: Update a comment (only by owner)
parameters:
- description: Comment ID (UUID)
in: path
name: id
required: true
type: string
- description: Updated comment content
in: body
name: comment
required: true
schema:
$ref: '#/definitions/internal_handlers.UpdateCommentRequest'
produces:
- application/json
responses:
"200":
description: OK
schema:
allOf:
- $ref: '#/definitions/internal_handlers.APIResponse'
- properties:
data:
properties:
comment:
type: object
type: object
type: object
"400":
description: Validation error
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
"401":
description: Unauthorized
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
"403":
description: Forbidden - can only edit own comments
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
"404":
description: Comment not found
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
"500":
description: Internal server error
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
security:
- BearerAuth: []
summary: Update comment
tags:
- Comment
/comments/{id}/replies:
get:
consumes:
- application/json
description: Get paginated list of replies to a comment
parameters:
- description: Parent Comment ID (UUID)
in: path
name: id
required: true
type: string
- default: 1
description: Page number
in: query
minimum: 1
name: page
type: integer
- default: 20
description: Items per page
in: query
maximum: 100
minimum: 1
name: limit
type: integer
produces:
- application/json
responses:
"200":
description: OK
schema:
allOf:
- $ref: '#/definitions/internal_handlers.APIResponse'
- properties:
data:
properties:
pagination:
type: object
replies:
type: array
type: object
type: object
"400":
description: Validation error
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
"404":
description: Parent comment not found
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
"500":
description: Internal server error
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
summary: Get comment replies
tags:
- Comment
/config/webrtc:
get:
description: Public — returns the ICE-server set the SPA feeds to RTCPeerConnection.
STUN-only when no TURN is configured. TURN credentials are always emitted
as static (REST shared-secret rotation deferred to v1.1).
produces:
- application/json
responses:
"200":
description: ICE servers
schema:
$ref: '#/definitions/internal_handlers.WebRTCConfigResponse'
summary: WebRTC ICE configuration
tags:
- Config
/internal/tracks/{id}/stream-ready:
post:
consumes:
- application/json
description: Internal endpoint called by the Rust stream server when HLS transcoding
completes or fails. Updates the track's stream_status and stream_manifest_url.
Requires internal API key (not user-facing).
parameters:
- description: Track UUID
in: path
name: id
required: true
type: string
- description: Callback payload
in: body
name: request
required: true
schema:
$ref: '#/definitions/internal_core_track.StreamCallbackRequest'
produces:
- application/json
responses:
"200":
description: OK
schema:
properties:
message:
type: string
type: object
"400":
description: Validation / invalid id
schema:
$ref: '#/definitions/veza-backend-api_internal_handlers.APIResponse'
"500":
description: Internal Error
schema:
$ref: '#/definitions/veza-backend-api_internal_handlers.APIResponse'
summary: Stream server callback
tags:
- Track
/playlists:
get:
consumes:
- application/json
description: Get a paginated list of playlists
parameters:
- default: 1
description: Page number
in: query
name: page
type: integer
- default: 20
description: Items per page
in: query
name: limit
type: integer
- description: Filter by User ID
in: query
name: user_id
type: string
produces:
- application/json
responses:
"200":
description: OK
schema:
allOf:
- $ref: '#/definitions/internal_handlers.APIResponse'
- properties:
data:
properties:
pagination:
type: object
playlists:
items:
$ref: '#/definitions/veza-backend-api_internal_models.Playlist'
type: array
type: object
type: object
"500":
description: Internal Error
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
security:
- BearerAuth: []
summary: Get Playlists
tags:
- Playlist
post:
consumes:
- application/json
description: Create a new playlist
parameters:
- description: Playlist Metadata
in: body
name: request
required: true
schema:
$ref: '#/definitions/internal_handlers.CreatePlaylistRequest'
produces:
- application/json
responses:
"201":
description: Created
schema:
allOf:
- $ref: '#/definitions/internal_handlers.APIResponse'
- properties:
data:
properties:
playlist:
$ref: '#/definitions/veza-backend-api_internal_models.Playlist'
type: object
type: object
"400":
description: Validation Error
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
"401":
description: Unauthorized
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
"500":
description: Internal Error
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
security:
- BearerAuth: []
summary: Create Playlist
tags:
- Playlist
/playlists/{id}:
delete:
consumes:
- application/json
description: Permanently delete a playlist
parameters:
- description: Playlist ID
in: path
name: id
required: true
type: string
produces:
- application/json
responses:
"200":
description: OK
schema:
allOf:
- $ref: '#/definitions/internal_handlers.APIResponse'
- properties:
data:
properties:
message:
type: string
type: object
type: object
"401":
description: Unauthorized
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
"403":
description: Forbidden
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
"404":
description: Playlist not found
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
security:
- BearerAuth: []
summary: Delete Playlist
tags:
- Playlist
get:
consumes:
- application/json
description: Get detailed information about a playlist
parameters:
- description: Playlist ID
in: path
name: id
required: true
type: string
produces:
- application/json
responses:
"200":
description: OK
schema:
allOf:
- $ref: '#/definitions/internal_handlers.APIResponse'
- properties:
data:
properties:
playlist:
$ref: '#/definitions/veza-backend-api_internal_models.Playlist'
type: object
type: object
"400":
description: Invalid ID
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
"404":
description: Playlist not found
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
security:
- BearerAuth: []
summary: Get Playlist by ID
tags:
- Playlist
put:
consumes:
- application/json
description: Update playlist metadata
parameters:
- description: Playlist ID
in: path
name: id
required: true
type: string
- description: Playlist Metadata
in: body
name: playlist
required: true
schema:
$ref: '#/definitions/internal_handlers.UpdatePlaylistRequest'
produces:
- application/json
responses:
"200":
description: OK
schema:
allOf:
- $ref: '#/definitions/internal_handlers.APIResponse'
- properties:
data:
properties:
playlist:
$ref: '#/definitions/veza-backend-api_internal_models.Playlist'
type: object
type: object
"400":
description: Validation Error
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
"401":
description: Unauthorized
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
"403":
description: Forbidden
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
"404":
description: Playlist not found
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
security:
- BearerAuth: []
summary: Update Playlist
tags:
- Playlist
/playlists/{id}/analytics:
get:
description: Returns aggregated stats for a playlist (plays, follows, tracks
count, etc.). Visible to the owner, collaborators and admins.
parameters:
- description: Playlist UUID
in: path
name: id
required: true
type: string
produces:
- application/json
responses:
"200":
description: OK
schema:
allOf:
- $ref: '#/definitions/internal_handlers.APIResponse'
- properties:
data:
properties:
stats:
type: object
type: object
type: object
"400":
description: Invalid id
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
"401":
description: Unauthorized
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
"403":
description: Forbidden
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
"404":
description: Playlist not found
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
"500":
description: Internal Error
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
security:
- BearerAuth: []
summary: Get playlist statistics
tags:
- Playlist
/playlists/{id}/collaborators:
get:
description: Returns the collaborators of a playlist with their permission level.
parameters:
- description: Playlist UUID
in: path
name: id
required: true
type: string
produces:
- application/json
responses:
"200":
description: OK
schema:
allOf:
- $ref: '#/definitions/internal_handlers.APIResponse'
- properties:
data:
properties:
collaborators:
items:
type: object
type: array
type: object
type: object
"400":
description: Invalid id
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
"401":
description: Unauthorized
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
"404":
description: Playlist not found
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
"500":
description: Internal Error
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
security:
- BearerAuth: []
summary: List playlist collaborators
tags:
- Playlist
post:
consumes:
- application/json
description: Invite a user as collaborator. Only the owner (or admin) can add.
parameters:
- description: Playlist UUID
in: path
name: id
required: true
type: string
- description: Collaborator + permission
in: body
name: request
required: true
schema:
$ref: '#/definitions/internal_handlers.AddCollaboratorRequest'
produces:
- application/json
responses:
"200":
description: OK
schema:
allOf:
- $ref: '#/definitions/internal_handlers.APIResponse'
- properties:
data:
properties:
collaborator:
type: object
type: object
type: object
"400":
description: Validation
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
"401":
description: Unauthorized
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
"403":
description: Not owner
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
"404":
description: Playlist not found
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
"500":
description: Internal Error
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
security:
- BearerAuth: []
summary: Add playlist collaborator
tags:
- Playlist
/playlists/{id}/collaborators/{userId}:
delete:
description: Revoke a collaborator's access. Only the owner (or admin) can remove.
parameters:
- description: Playlist UUID
in: path
name: id
required: true
type: string
- description: Collaborator user UUID
in: path
name: userId
required: true
type: string
produces:
- application/json
responses:
"200":
description: OK
schema:
allOf:
- $ref: '#/definitions/internal_handlers.APIResponse'
- properties:
data:
properties:
message:
type: string
type: object
type: object
"400":
description: Validation
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
"401":
description: Unauthorized
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
"403":
description: Not owner
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
"404":
description: Playlist or collaborator not found
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
"500":
description: Internal Error
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
security:
- BearerAuth: []
summary: Remove playlist collaborator
tags:
- Playlist
put:
consumes:
- application/json
description: Change a collaborator's permission level (read / write / admin).
Only the owner can update.
parameters:
- description: Playlist UUID
in: path
name: id
required: true
type: string
- description: Collaborator user UUID
in: path
name: userId
required: true
type: string
- description: New permission
in: body
name: request
required: true
schema:
$ref: '#/definitions/internal_handlers.UpdateCollaboratorPermissionRequest'
produces:
- application/json
responses:
"200":
description: OK
schema:
allOf:
- $ref: '#/definitions/internal_handlers.APIResponse'
- properties:
data:
properties:
collaborator:
type: object
type: object
type: object
"400":
description: Validation
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
"401":
description: Unauthorized
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
"403":
description: Not owner
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
"404":
description: Playlist or collaborator not found
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
"500":
description: Internal Error
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
security:
- BearerAuth: []
summary: Update collaborator permission
tags:
- Playlist
/playlists/{id}/duplicate:
post:
description: Copy a playlist's track list into a new playlist owned by the authenticated
user. Cover/description copied; original unchanged.
parameters:
- description: Source playlist UUID
in: path
name: id
required: true
type: string
produces:
- application/json
responses:
"201":
description: Created
schema:
allOf:
- $ref: '#/definitions/internal_handlers.APIResponse'
- properties:
data:
properties:
playlist:
$ref: '#/definitions/veza-backend-api_internal_models.Playlist'
type: object
type: object
"400":
description: Invalid id
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
"401":
description: Unauthorized
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
"403":
description: Source not visible
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
"404":
description: Source playlist not found
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
"500":
description: Internal Error
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
security:
- BearerAuth: []
summary: Duplicate playlist
tags:
- Playlist
/playlists/{id}/share:
post:
description: Generate a tokenised link to share a playlist (read-only). Only
owner / admin can issue. No body required.
parameters:
- description: Playlist UUID
in: path
name: id
required: true
type: string
produces:
- application/json
responses:
"200":
description: OK
schema:
allOf:
- $ref: '#/definitions/internal_handlers.APIResponse'
- properties:
data:
properties:
share:
type: object
type: object
type: object
"400":
description: Validation
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
"401":
description: Unauthorized
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
"403":
description: Not owner
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
"404":
description: Playlist not found
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
"500":
description: Internal Error
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
security:
- BearerAuth: []
summary: Create playlist share link
tags:
- Playlist
/playlists/{id}/tracks:
post:
consumes:
- application/json
description: Add a track to the playlist
parameters:
- description: Playlist ID
in: path
name: id
required: true
type: string
- description: Track ID (in body)
in: body
name: trackId
required: true
schema:
properties:
track_id:
type: string
type: object
produces:
- application/json
responses:
"200":
description: OK
schema:
allOf:
- $ref: '#/definitions/internal_handlers.APIResponse'
- properties:
data:
properties:
message:
type: string
type: object
type: object
"400":
description: Track already present or invalid ID
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
"404":
description: Playlist or Track not found
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
security:
- BearerAuth: []
summary: Add Track to Playlist
tags:
- Playlist
/playlists/{id}/tracks/{trackId}:
delete:
consumes:
- application/json
description: Remove a track from the playlist
parameters:
- description: Playlist ID
in: path
name: id
required: true
type: string
- description: Track ID
in: path
name: trackId
required: true
type: string
produces:
- application/json
responses:
"200":
description: OK
schema:
allOf:
- $ref: '#/definitions/internal_handlers.APIResponse'
- properties:
data:
properties:
message:
type: string
type: object
type: object
"404":
description: Playlist or Track not found
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
security:
- BearerAuth: []
summary: Remove Track from Playlist
tags:
- Playlist
/playlists/{id}/tracks/reorder:
put:
consumes:
- application/json
description: Reorder tracks in the playlist
parameters:
- description: Playlist ID
in: path
name: id
required: true
type: string
- description: New Track Order
in: body
name: order
required: true
schema:
$ref: '#/definitions/internal_handlers.ReorderTracksRequest'
produces:
- application/json
responses:
"200":
description: OK
schema:
allOf:
- $ref: '#/definitions/internal_handlers.APIResponse'
- properties:
data:
properties:
message:
type: string
type: object
type: object
"400":
description: Validation Error
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
security:
- BearerAuth: []
summary: Reorder Tracks
tags:
- Playlist
/playlists/favoris:
get:
description: Returns the authenticated user's "Favoris" playlist. Auto-created
on first call. Used by the like-as-save pattern.
produces:
- application/json
responses:
"200":
description: OK
schema:
allOf:
- $ref: '#/definitions/internal_handlers.APIResponse'
- properties:
data:
properties:
playlist:
$ref: '#/definitions/veza-backend-api_internal_models.Playlist'
type: object
type: object
"401":
description: Unauthorized
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
"500":
description: Internal Error
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
security:
- BearerAuth: []
summary: Get Favoris playlist
tags:
- Playlist
/playlists/import:
post:
consumes:
- application/json
description: Create a playlist from a JSON payload (title, description, is_public,
ordered track IDs). Useful for bulk seed / migration.
parameters:
- description: Playlist + tracks
in: body
name: request
required: true
schema:
$ref: '#/definitions/internal_handlers.ImportPlaylistRequest'
produces:
- application/json
responses:
"201":
description: Created
schema:
allOf:
- $ref: '#/definitions/internal_handlers.APIResponse'
- properties:
data:
properties:
playlist:
$ref: '#/definitions/veza-backend-api_internal_models.Playlist'
type: object
type: object
"400":
description: Validation
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
"401":
description: Unauthorized
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
"500":
description: Internal Error
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
security:
- BearerAuth: []
summary: Import playlist
tags:
- Playlist
/playlists/recommendations:
get:
description: Suggested playlists for the authenticated user. Chronological /
declarative discovery — no behavioural ranking (CLAUDE.md rule 7).
parameters:
- default: 20
description: Max items (max 100)
in: query
name: limit
type: integer
produces:
- application/json
responses:
"200":
description: OK
schema:
allOf:
- $ref: '#/definitions/internal_handlers.APIResponse'
- properties:
data:
properties:
playlists:
items:
$ref: '#/definitions/veza-backend-api_internal_models.Playlist'
type: array
type: object
type: object
"401":
description: Unauthorized
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
"500":
description: Internal Error
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
security:
- BearerAuth: []
summary: Get playlist recommendations
tags:
- Playlist
/playlists/search:
get:
description: Full-text search on public playlists (title + description). Paginated.
parameters:
- description: Full-text query
in: query
name: q
type: string
- default: 1
description: Page number
in: query
name: page
type: integer
- default: 20
description: Items per page (max 100)
in: query
name: limit
type: integer
produces:
- application/json
responses:
"200":
description: OK
schema:
allOf:
- $ref: '#/definitions/internal_handlers.APIResponse'
- properties:
data:
properties:
pagination:
type: object
playlists:
items:
$ref: '#/definitions/veza-backend-api_internal_models.Playlist'
type: array
type: object
type: object
"400":
description: Validation
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
"500":
description: Internal Error
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
summary: Search playlists
tags:
- Playlist
/playlists/shared/{token}:
get:
description: Public endpoint resolving a share token. Allows unauthenticated
access to the playlist snapshot + tracks.
parameters:
- description: Share token
in: path
name: token
required: true
type: string
produces:
- application/json
responses:
"200":
description: OK
schema:
allOf:
- $ref: '#/definitions/internal_handlers.APIResponse'
- properties:
data:
properties:
playlist:
$ref: '#/definitions/veza-backend-api_internal_models.Playlist'
type: object
type: object
"400":
description: Missing token
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
"403":
description: Share expired
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
"404":
description: Share or playlist not found
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
"500":
description: Internal Error
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
summary: Get playlist by share token
tags:
- Playlist
/queue:
delete:
consumes:
- application/json
description: Removes every item from the authenticated user's playback queue
produces:
- application/json
responses:
"200":
description: Queue cleared
schema:
allOf:
- $ref: '#/definitions/internal_handlers.APIResponse'
- properties:
data:
properties:
message:
type: string
type: object
type: object
"401":
description: Unauthorized
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
"500":
description: Internal Error
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
security:
- BearerAuth: []
summary: Clear queue
tags:
- Queue
get:
consumes:
- application/json
description: Returns the authenticated user's persistent playback queue with
all items in position order
produces:
- application/json
responses:
"200":
description: Queue + items
schema:
allOf:
- $ref: '#/definitions/internal_handlers.APIResponse'
- properties:
data:
properties:
items:
items:
type: object
type: array
queue:
type: object
type: object
type: object
"401":
description: Unauthorized
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
"500":
description: Internal Error
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
security:
- BearerAuth: []
summary: Get user playback queue
tags:
- Queue
put:
consumes:
- application/json
description: Updates the authenticated user's queue state (current track / position
/ playback flags / item order)
parameters:
- description: Queue update payload
in: body
name: request
required: true
schema:
$ref: '#/definitions/veza-backend-api_internal_services.UpdateQueueRequest'
produces:
- application/json
responses:
"200":
description: Updated queue
schema:
allOf:
- $ref: '#/definitions/internal_handlers.APIResponse'
- properties:
data:
properties:
items:
items:
type: object
type: array
queue:
type: object
type: object
type: object
"400":
description: Validation error
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
"401":
description: Unauthorized
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
"500":
description: Internal Error
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
security:
- BearerAuth: []
summary: Update user playback queue
tags:
- Queue
/queue/items:
post:
consumes:
- application/json
description: Appends a track to the authenticated user's playback queue
parameters:
- description: Track to enqueue
in: body
name: request
required: true
schema:
$ref: '#/definitions/internal_handlers.AddQueueItemRequest'
produces:
- application/json
responses:
"201":
description: Created queue item
schema:
allOf:
- $ref: '#/definitions/internal_handlers.APIResponse'
- properties:
data:
properties:
item:
type: object
type: object
type: object
"400":
description: Validation error
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
"401":
description: Unauthorized
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
"500":
description: Internal Error
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
security:
- BearerAuth: []
summary: Add track to queue
tags:
- Queue
/queue/items/{id}:
delete:
consumes:
- application/json
description: Removes a single item from the authenticated user's playback queue
by item ID
parameters:
- description: Queue item ID (UUID)
in: path
name: id
required: true
type: string
produces:
- application/json
responses:
"200":
description: Item removed
schema:
allOf:
- $ref: '#/definitions/internal_handlers.APIResponse'
- properties:
data:
properties:
message:
type: string
type: object
type: object
"400":
description: Invalid item ID
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
"401":
description: Unauthorized
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
"404":
description: Queue item not found
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
security:
- BearerAuth: []
summary: Remove queue item
tags:
- Queue
/queue/session:
post:
consumes:
- application/json
description: Creates a shared queue session and returns its share token + URL.
The session creator is recorded as host.
produces:
- application/json
responses:
"201":
description: Created session
schema:
allOf:
- $ref: '#/definitions/internal_handlers.APIResponse'
- properties:
data:
properties:
session:
type: object
share_token:
type: string
share_url:
type: string
type: object
type: object
"401":
description: Unauthorized
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
"500":
description: Internal Error
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
security:
- BearerAuth: []
summary: Create collaborative queue session
tags:
- Queue
/queue/session/{token}:
delete:
consumes:
- application/json
description: Deletes a collaborative queue session. Only the original session
creator can delete.
parameters:
- description: Session share token
in: path
name: token
required: true
type: string
produces:
- application/json
responses:
"200":
description: Session deleted
schema:
allOf:
- $ref: '#/definitions/internal_handlers.APIResponse'
- properties:
data:
properties:
message:
type: string
type: object
type: object
"400":
description: Token required
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
"401":
description: Unauthorized
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
"403":
description: Only the creator can delete this session
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
"404":
description: Session not found
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
security:
- BearerAuth: []
summary: Delete queue session
tags:
- Queue
get:
consumes:
- application/json
description: Returns the session metadata + items for a given share token. No
auth required (public — anyone with the link can join).
parameters:
- description: Session share token
in: path
name: token
required: true
type: string
produces:
- application/json
responses:
"200":
description: Session and queue items
schema:
allOf:
- $ref: '#/definitions/internal_handlers.APIResponse'
- properties:
data:
properties:
items:
items:
type: object
type: array
session:
type: object
type: object
type: object
"400":
description: Token required
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
"404":
description: Session not found
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
"500":
description: Internal Error
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
summary: Get queue session by share token
tags:
- Queue
/queue/session/{token}/items:
post:
consumes:
- application/json
description: Adds a track to a collaborative queue session. Anyone with the
share token can add.
parameters:
- description: Session share token
in: path
name: token
required: true
type: string
- description: Track to enqueue
in: body
name: request
required: true
schema:
$ref: '#/definitions/internal_handlers.AddToSessionRequest'
produces:
- application/json
responses:
"201":
description: Updated session and items
schema:
allOf:
- $ref: '#/definitions/internal_handlers.APIResponse'
- properties:
data:
properties:
items:
items:
type: object
type: array
session:
type: object
type: object
type: object
"400":
description: Validation error
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
"404":
description: Session not found
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
"500":
description: Internal Error
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
security:
- BearerAuth: []
summary: Add track to queue session
tags:
- Queue
/queue/session/{token}/items/{id}:
delete:
consumes:
- application/json
description: Removes an item from a collaborative queue session by item ID
parameters:
- description: Session share token
in: path
name: token
required: true
type: string
- description: Queue item ID (UUID)
in: path
name: id
required: true
type: string
produces:
- application/json
responses:
"200":
description: Item removed
schema:
allOf:
- $ref: '#/definitions/internal_handlers.APIResponse'
- properties:
data:
properties:
message:
type: string
type: object
type: object
"400":
description: Validation error
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
"404":
description: Session or item not found
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
"500":
description: Internal Error
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
security:
- BearerAuth: []
summary: Remove item from queue session
tags:
- Queue
/search:
get:
description: Postgres FTS-backed search across tracks, users, and playlists.
Optional `type` filter accepts repeated values (e.g., ?type=track&type=user).
v1.0.9 item 1.6 — annotation added so orval can generate a typed client.
parameters:
- description: Search query
in: query
name: q
required: true
type: string
- collectionFormat: multi
description: 'Restrict to one or more entity types: track, user, playlist'
in: query
items:
type: string
name: type
type: array
- description: Opaque pagination cursor
in: query
name: cursor
type: string
- description: Page size (max 50)
in: query
name: limit
type: integer
produces:
- application/json
responses:
"200":
description: Search results
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
"400":
description: Validation error
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
"500":
description: Search failed
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
summary: Unified search
tags:
- Search
/search/suggestions:
get:
description: Lightweight autocomplete used by the search bar. Returns a small
SearchResult subset (typically tracks + users + playlists), capped at `limit`
(1..20, default 5). v1.0.9 item 1.6 — annotation added so orval can generate
a typed client.
parameters:
- description: Partial query (min 1 char)
in: query
name: q
required: true
type: string
- description: Max number of suggestions (1..20, default 5)
in: query
name: limit
type: integer
produces:
- application/json
responses:
"200":
description: Suggestions
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
"400":
description: Validation error
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
"500":
description: Suggestions failed
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
summary: Search suggestions
tags:
- Search
/social/trending:
get:
description: Returns the top hashtags surfacing in posts published recently.
Counts are aggregated, not user-personalised — discovery is by declarative
tags, not behavioural ranking (cf. CLAUDE.md rule 7). v1.0.9 item 1.6 — annotation
added so orval can generate a typed client.
parameters:
- description: Max tags to return (1..50, default 10)
in: query
name: limit
type: integer
produces:
- application/json
responses:
"200":
description: Trending tags
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
"500":
description: Failed to compute trending
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
summary: Trending hashtags
tags:
- Social
/tracks:
get:
description: List tracks with pagination, filters, sort. Cursor-based when ?cursor
provided, otherwise page/limit offset.
parameters:
- description: Opaque pagination cursor (overrides page)
in: query
name: cursor
type: string
- default: 1
description: Page number, 1-based (ignored if cursor set)
in: query
name: page
type: integer
- default: 20
description: Items per page (max 100)
in: query
name: limit
type: integer
- description: Filter by creator UUID
in: query
name: user_id
type: string
- description: Filter by genre
in: query
name: genre
type: string
- description: Filter by audio format (mp3, flac, wav, ogg, m4a, aac)
in: query
name: format
type: string
- default: created_at
description: Sort column (created_at, play_count, title)
in: query
name: sort_by
type: string
produces:
- application/json
responses:
"200":
description: OK
schema:
allOf:
- $ref: '#/definitions/veza-backend-api_internal_response.APIResponse'
- properties:
data:
properties:
pagination:
type: object
tracks:
items:
$ref: '#/definitions/veza-backend-api_internal_models.Track'
type: array
type: object
type: object
"400":
description: Invalid query params
schema:
$ref: '#/definitions/veza-backend-api_internal_response.APIResponse'
"500":
description: Internal Error
schema:
$ref: '#/definitions/veza-backend-api_internal_response.APIResponse'
summary: List tracks
tags:
- Track
post:
consumes:
- multipart/form-data
description: Upload a new track (audio file)
parameters:
- description: Audio File (MP3, WAV, FLAC, OGG)
in: formData
name: file
required: true
type: file
produces:
- application/json
responses:
"201":
description: Created
schema:
allOf:
- $ref: '#/definitions/veza-backend-api_internal_response.APIResponse'
- properties:
data:
properties:
track:
$ref: '#/definitions/veza-backend-api_internal_models.Track'
type: object
type: object
"400":
description: No file or validation error
schema:
$ref: '#/definitions/veza-backend-api_internal_response.APIResponse'
"401":
description: Unauthorized
schema:
$ref: '#/definitions/veza-backend-api_internal_response.APIResponse'
"403":
description: Quota exceeded
schema:
$ref: '#/definitions/veza-backend-api_internal_response.APIResponse'
"500":
description: Internal Error
schema:
$ref: '#/definitions/veza-backend-api_internal_response.APIResponse'
security:
- BearerAuth: []
summary: Upload Track
tags:
- Track
/tracks/{id}:
delete:
description: Soft-delete a track (sets deleted_at). Caller must own the track
or be admin.
parameters:
- description: Track UUID
in: path
name: id
required: true
type: string
produces:
- application/json
responses:
"200":
description: OK
schema:
allOf:
- $ref: '#/definitions/veza-backend-api_internal_response.APIResponse'
- properties:
data:
properties:
message:
type: string
type: object
type: object
"400":
description: Invalid track id
schema:
$ref: '#/definitions/veza-backend-api_internal_response.APIResponse'
"401":
description: Unauthorized
schema:
$ref: '#/definitions/veza-backend-api_internal_response.APIResponse'
"403":
description: Not owner / no admin
schema:
$ref: '#/definitions/veza-backend-api_internal_response.APIResponse'
"404":
description: Track not found
schema:
$ref: '#/definitions/veza-backend-api_internal_response.APIResponse'
"500":
description: Internal Error
schema:
$ref: '#/definitions/veza-backend-api_internal_response.APIResponse'
security:
- BearerAuth: []
summary: Delete track
tags:
- Track
get:
description: Retrieve a single track. Private play_count / like_count are omitted
for non-owners (v0.10.3 F202).
parameters:
- description: Track UUID
in: path
name: id
required: true
type: string
produces:
- application/json
responses:
"200":
description: OK
schema:
allOf:
- $ref: '#/definitions/veza-backend-api_internal_response.APIResponse'
- properties:
data:
properties:
track:
$ref: '#/definitions/veza-backend-api_internal_models.Track'
type: object
type: object
"400":
description: Invalid track id
schema:
$ref: '#/definitions/veza-backend-api_internal_response.APIResponse'
"404":
description: Track not found
schema:
$ref: '#/definitions/veza-backend-api_internal_response.APIResponse'
"500":
description: Internal Error
schema:
$ref: '#/definitions/veza-backend-api_internal_response.APIResponse'
summary: Get track by ID
tags:
- Track
put:
consumes:
- application/json
description: Update the metadata of an existing track. Caller must own the track
or be admin.
parameters:
- description: Track UUID
in: path
name: id
required: true
type: string
- description: Updated metadata
in: body
name: request
required: true
schema:
$ref: '#/definitions/internal_core_track.UpdateTrackRequest'
produces:
- application/json
responses:
"200":
description: OK
schema:
allOf:
- $ref: '#/definitions/veza-backend-api_internal_response.APIResponse'
- properties:
data:
properties:
track:
$ref: '#/definitions/veza-backend-api_internal_models.Track'
type: object
type: object
"400":
description: Validation / invalid id
schema:
$ref: '#/definitions/veza-backend-api_internal_response.APIResponse'
"401":
description: Unauthorized
schema:
$ref: '#/definitions/veza-backend-api_internal_response.APIResponse'
"403":
description: Not owner / no admin
schema:
$ref: '#/definitions/veza-backend-api_internal_response.APIResponse'
"404":
description: Track not found
schema:
$ref: '#/definitions/veza-backend-api_internal_response.APIResponse'
"500":
description: Internal Error
schema:
$ref: '#/definitions/veza-backend-api_internal_response.APIResponse'
security:
- BearerAuth: []
summary: Update track metadata
tags:
- Track
/tracks/{id}/comments:
get:
consumes:
- application/json
description: Get paginated list of comments for a track
parameters:
- description: Track ID
in: path
name: id
required: true
type: string
- default: 1
description: Page number
in: query
name: page
type: integer
- default: 20
description: Items per page
in: query
name: limit
type: integer
produces:
- application/json
responses:
"200":
description: OK
schema:
allOf:
- $ref: '#/definitions/internal_handlers.APIResponse'
- properties:
data:
properties:
comments:
type: array
pagination:
type: object
type: object
type: object
"400":
description: Validation error
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
"404":
description: Track not found
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
"500":
description: Internal server error
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
summary: Get track comments
tags:
- Comment
post:
consumes:
- application/json
description: Create a new comment on a track. Can be a top-level comment or
a reply to another comment (using parent_id).
parameters:
- description: Track ID (UUID)
in: path
name: id
required: true
type: string
- description: Comment data
in: body
name: comment
required: true
schema:
$ref: '#/definitions/internal_handlers.CreateCommentRequest'
produces:
- application/json
responses:
"201":
description: Created
schema:
allOf:
- $ref: '#/definitions/internal_handlers.APIResponse'
- properties:
data:
properties:
comment:
type: object
type: object
type: object
"400":
description: Validation error
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
"401":
description: Unauthorized
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
"404":
description: Track not found
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
"500":
description: Internal server error
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
security:
- BearerAuth: []
summary: Create comment
tags:
- Comment
/tracks/{id}/comments/{comment_id}:
delete:
consumes:
- application/json
description: Delete a comment (only by owner or admin)
parameters:
- description: Track ID
in: path
name: id
required: true
type: string
- description: Comment ID
in: path
name: comment_id
required: true
type: string
produces:
- application/json
responses:
"200":
description: OK
schema:
allOf:
- $ref: '#/definitions/internal_handlers.APIResponse'
- properties:
data:
properties:
message:
type: string
type: object
type: object
"400":
description: Validation error
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
"401":
description: Unauthorized
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
"403":
description: Forbidden - not comment owner
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
"404":
description: Comment not found
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
security:
- BearerAuth: []
summary: Delete comment
tags:
- Comment
/tracks/{id}/download:
get:
description: Serve the original audio file. For S3-backed tracks returns a 302
redirect to a signed URL (TTL 30min). For local-backed tracks streams the
file with Range support. Public tracks or share_token access; paid tracks
require a license.
parameters:
- description: Track UUID
in: path
name: id
required: true
type: string
- description: Grants access without authentication for a limited time
in: query
name: share_token
type: string
produces:
- application/octet-stream
responses:
"200":
description: OK
schema:
type: file
"302":
description: Location header points to signed S3 URL (s3-backed tracks)
schema:
type: string
"400":
description: Invalid track id
schema:
$ref: '#/definitions/veza-backend-api_internal_handlers.APIResponse'
"403":
description: No permission / license required
schema:
$ref: '#/definitions/veza-backend-api_internal_handlers.APIResponse'
"404":
description: Track or file not found
schema:
$ref: '#/definitions/veza-backend-api_internal_handlers.APIResponse'
"500":
description: Internal Error
schema:
$ref: '#/definitions/veza-backend-api_internal_handlers.APIResponse'
summary: Download a track
tags:
- Track
/tracks/{id}/history:
get:
description: Paginated audit log of modifications (metadata updates, version
changes) for a track.
parameters:
- description: Track UUID
in: path
name: id
required: true
type: string
- default: 50
description: Items per page
in: query
name: limit
type: integer
- default: 0
description: Offset
in: query
name: offset
type: integer
produces:
- application/json
responses:
"200":
description: OK
schema:
allOf:
- $ref: '#/definitions/veza-backend-api_internal_handlers.APIResponse'
- properties:
data:
properties:
history:
items:
type: object
type: array
limit:
type: integer
offset:
type: integer
total:
type: integer
type: object
type: object
"400":
description: Invalid track id
schema:
$ref: '#/definitions/veza-backend-api_internal_handlers.APIResponse'
"404":
description: Track not found
schema:
$ref: '#/definitions/veza-backend-api_internal_handlers.APIResponse'
"500":
description: Internal Error
schema:
$ref: '#/definitions/veza-backend-api_internal_handlers.APIResponse'
summary: Get track history
tags:
- Track
/tracks/{id}/like:
delete:
description: Remove the authenticated user's like on the track (idempotent).
parameters:
- description: Track UUID
in: path
name: id
required: true
type: string
produces:
- application/json
responses:
"200":
description: OK
schema:
allOf:
- $ref: '#/definitions/veza-backend-api_internal_handlers.APIResponse'
- properties:
data:
properties:
message:
type: string
type: object
type: object
"400":
description: Invalid track id
schema:
$ref: '#/definitions/veza-backend-api_internal_handlers.APIResponse'
"401":
description: Unauthorized
schema:
$ref: '#/definitions/veza-backend-api_internal_handlers.APIResponse'
"500":
description: Internal Error
schema:
$ref: '#/definitions/veza-backend-api_internal_handlers.APIResponse'
security:
- BearerAuth: []
summary: Unlike a track
tags:
- Track
post:
description: Record a like from the authenticated user. Creates a grouped notification
for the creator (F554).
parameters:
- description: Track UUID
in: path
name: id
required: true
type: string
produces:
- application/json
responses:
"200":
description: OK
schema:
allOf:
- $ref: '#/definitions/veza-backend-api_internal_handlers.APIResponse'
- properties:
data:
properties:
message:
type: string
type: object
type: object
"400":
description: Invalid track id
schema:
$ref: '#/definitions/veza-backend-api_internal_handlers.APIResponse'
"401":
description: Unauthorized
schema:
$ref: '#/definitions/veza-backend-api_internal_handlers.APIResponse'
"404":
description: Track not found
schema:
$ref: '#/definitions/veza-backend-api_internal_handlers.APIResponse'
"500":
description: Internal Error
schema:
$ref: '#/definitions/veza-backend-api_internal_handlers.APIResponse'
security:
- BearerAuth: []
summary: Like a track
tags:
- Track
/tracks/{id}/likes:
get:
description: Returns whether the current user has liked the track. The total
like count is returned ONLY to the creator or an admin (privacy per ORIGIN_UI_UX_SYSTEM
§13).
parameters:
- description: Track UUID
in: path
name: id
required: true
type: string
produces:
- application/json
responses:
"200":
description: count is omitted for non-owners
schema:
allOf:
- $ref: '#/definitions/veza-backend-api_internal_handlers.APIResponse'
- properties:
data:
properties:
count:
type: integer
is_liked:
type: boolean
type: object
type: object
"400":
description: Invalid track id
schema:
$ref: '#/definitions/veza-backend-api_internal_handlers.APIResponse'
"401":
description: Unauthorized
schema:
$ref: '#/definitions/veza-backend-api_internal_handlers.APIResponse'
"404":
description: Track not found
schema:
$ref: '#/definitions/veza-backend-api_internal_handlers.APIResponse'
"500":
description: Internal Error
schema:
$ref: '#/definitions/veza-backend-api_internal_handlers.APIResponse'
security:
- BearerAuth: []
summary: Get track like status
tags:
- Track
/tracks/{id}/lyrics:
get:
description: Returns the current lyrics for a track, or null if no lyrics exist.
parameters:
- description: Track UUID
in: path
name: id
required: true
type: string
produces:
- application/json
responses:
"200":
description: lyrics may be null
schema:
allOf:
- $ref: '#/definitions/veza-backend-api_internal_response.APIResponse'
- properties:
data:
properties:
lyrics:
type: object
type: object
type: object
"400":
description: Invalid track id
schema:
$ref: '#/definitions/veza-backend-api_internal_response.APIResponse'
"404":
description: Track not found
schema:
$ref: '#/definitions/veza-backend-api_internal_response.APIResponse'
"500":
description: Internal Error
schema:
$ref: '#/definitions/veza-backend-api_internal_response.APIResponse'
summary: Get track lyrics
tags:
- Track
put:
consumes:
- application/json
description: Replace the lyrics of a track. Caller must own the track or be
admin.
parameters:
- description: Track UUID
in: path
name: id
required: true
type: string
- description: Lyrics payload
in: body
name: request
required: true
schema:
$ref: '#/definitions/internal_core_track.UpdateLyricsRequest'
produces:
- application/json
responses:
"200":
description: OK
schema:
allOf:
- $ref: '#/definitions/veza-backend-api_internal_response.APIResponse'
- properties:
data:
properties:
lyrics:
type: object
type: object
type: object
"400":
description: Validation / invalid id
schema:
$ref: '#/definitions/veza-backend-api_internal_response.APIResponse'
"401":
description: Unauthorized
schema:
$ref: '#/definitions/veza-backend-api_internal_response.APIResponse'
"403":
description: Not owner / no admin
schema:
$ref: '#/definitions/veza-backend-api_internal_response.APIResponse'
"404":
description: Track not found
schema:
$ref: '#/definitions/veza-backend-api_internal_response.APIResponse'
"500":
description: Internal Error
schema:
$ref: '#/definitions/veza-backend-api_internal_response.APIResponse'
security:
- BearerAuth: []
summary: Create or update track lyrics
tags:
- Track
/tracks/{id}/play:
post:
consumes:
- application/json
description: Persist a playback event with optional play_time so the creator's
analytics dashboard tracks listening behaviour.
parameters:
- description: Track UUID
in: path
name: id
required: true
type: string
- description: Playback metadata (optional)
in: body
name: request
schema:
$ref: '#/definitions/internal_core_track.RecordPlayRequest'
produces:
- application/json
responses:
"200":
description: OK
schema:
allOf:
- $ref: '#/definitions/veza-backend-api_internal_handlers.APIResponse'
- properties:
data:
properties:
id:
type: string
message:
type: string
type: object
type: object
"400":
description: Invalid track id / body
schema:
$ref: '#/definitions/veza-backend-api_internal_handlers.APIResponse'
"401":
description: Unauthorized
schema:
$ref: '#/definitions/veza-backend-api_internal_handlers.APIResponse'
"404":
description: Track not found
schema:
$ref: '#/definitions/veza-backend-api_internal_handlers.APIResponse'
"500":
description: Internal Error
schema:
$ref: '#/definitions/veza-backend-api_internal_handlers.APIResponse'
security:
- BearerAuth: []
summary: Record play event
tags:
- Track
/tracks/{id}/repost:
delete:
description: Remove the authenticated user's repost of the track (idempotent).
parameters:
- description: Track UUID
in: path
name: id
required: true
type: string
produces:
- application/json
responses:
"200":
description: OK
schema:
allOf:
- $ref: '#/definitions/veza-backend-api_internal_handlers.APIResponse'
- properties:
data:
properties:
message:
type: string
type: object
type: object
"400":
description: Invalid track id
schema:
$ref: '#/definitions/veza-backend-api_internal_handlers.APIResponse'
"401":
description: Unauthorized
schema:
$ref: '#/definitions/veza-backend-api_internal_handlers.APIResponse'
"500":
description: Internal Error
schema:
$ref: '#/definitions/veza-backend-api_internal_handlers.APIResponse'
security:
- BearerAuth: []
summary: Remove track repost
tags:
- Track
get:
description: Returns whether the current user has reposted the track. Public
(optional auth); unauthenticated callers get is_reposted=false.
parameters:
- description: Track UUID
in: path
name: id
required: true
type: string
produces:
- application/json
responses:
"200":
description: OK
schema:
allOf:
- $ref: '#/definitions/veza-backend-api_internal_handlers.APIResponse'
- properties:
data:
properties:
is_reposted:
type: boolean
type: object
type: object
"400":
description: Invalid track id
schema:
$ref: '#/definitions/veza-backend-api_internal_handlers.APIResponse'
summary: Get repost status
tags:
- Track
post:
description: Add a track to the authenticated user's profile as a repost. Notifies
the creator (F204) unless self-repost.
parameters:
- description: Track UUID
in: path
name: id
required: true
type: string
produces:
- application/json
responses:
"200":
description: OK
schema:
allOf:
- $ref: '#/definitions/veza-backend-api_internal_handlers.APIResponse'
- properties:
data:
properties:
message:
type: string
type: object
type: object
"400":
description: Invalid track id
schema:
$ref: '#/definitions/veza-backend-api_internal_handlers.APIResponse'
"401":
description: Unauthorized
schema:
$ref: '#/definitions/veza-backend-api_internal_handlers.APIResponse'
"404":
description: Track not found
schema:
$ref: '#/definitions/veza-backend-api_internal_handlers.APIResponse'
"500":
description: Internal Error
schema:
$ref: '#/definitions/veza-backend-api_internal_handlers.APIResponse'
security:
- BearerAuth: []
summary: Repost a track
tags:
- Track
/tracks/{id}/share:
post:
consumes:
- application/json
description: Generate a tokenized share link for a track with given permission
level and optional expiry.
parameters:
- description: Track UUID
in: path
name: id
required: true
type: string
- description: Share parameters
in: body
name: request
required: true
schema:
$ref: '#/definitions/internal_core_track.CreateShareRequest'
produces:
- application/json
responses:
"200":
description: OK
schema:
allOf:
- $ref: '#/definitions/veza-backend-api_internal_handlers.APIResponse'
- properties:
data:
properties:
share:
type: object
type: object
type: object
"400":
description: Validation
schema:
$ref: '#/definitions/veza-backend-api_internal_handlers.APIResponse'
"401":
description: Unauthorized
schema:
$ref: '#/definitions/veza-backend-api_internal_handlers.APIResponse'
"403":
description: Not owner
schema:
$ref: '#/definitions/veza-backend-api_internal_handlers.APIResponse'
"404":
description: Track not found
schema:
$ref: '#/definitions/veza-backend-api_internal_handlers.APIResponse'
"500":
description: Internal Error
schema:
$ref: '#/definitions/veza-backend-api_internal_handlers.APIResponse'
security:
- BearerAuth: []
summary: Create share link
tags:
- Track
/tracks/{id}/stats:
get:
description: 'Aggregated track stats: views, likes, comments, play time, downloads,
average duration.'
parameters:
- description: Track UUID
in: path
name: id
required: true
type: string
produces:
- application/json
responses:
"200":
description: OK
schema:
allOf:
- $ref: '#/definitions/veza-backend-api_internal_handlers.APIResponse'
- properties:
data:
properties:
stats:
type: object
type: object
type: object
"400":
description: Invalid track id
schema:
$ref: '#/definitions/veza-backend-api_internal_handlers.APIResponse'
"404":
description: Track not found
schema:
$ref: '#/definitions/veza-backend-api_internal_handlers.APIResponse'
"500":
description: Internal Error
schema:
$ref: '#/definitions/veza-backend-api_internal_handlers.APIResponse'
summary: Get track statistics
tags:
- Track
/tracks/{id}/status:
get:
consumes:
- application/json
description: Get the processing status of an uploaded track
parameters:
- description: Track ID
in: path
name: id
required: true
type: string
produces:
- application/json
responses:
"200":
description: OK
schema:
allOf:
- $ref: '#/definitions/veza-backend-api_internal_response.APIResponse'
- properties:
data:
properties:
progress:
type: integer
type: object
type: object
"400":
description: Invalid ID
schema:
$ref: '#/definitions/veza-backend-api_internal_response.APIResponse'
"401":
description: Unauthorized
schema:
$ref: '#/definitions/veza-backend-api_internal_response.APIResponse'
"404":
description: Track not found
schema:
$ref: '#/definitions/veza-backend-api_internal_response.APIResponse'
security:
- BearerAuth: []
summary: Get Upload Status
tags:
- Track
/tracks/{id}/stream:
get:
description: Default playback path. S3-backed tracks return a 302 redirect to
a signed URL (TTL 15min). Local-backed tracks are streamed via http.ServeContent
with Range support. Always available, unlike /hls/* which is gated by HLSEnabled.
parameters:
- description: Track UUID
in: path
name: id
required: true
type: string
- description: Grants access without authentication
in: query
name: share_token
type: string
produces:
- audio/*
responses:
"200":
description: OK
schema:
type: file
"302":
description: Location header points to signed S3 URL (s3-backed tracks)
schema:
type: string
"400":
description: Invalid track id
schema:
$ref: '#/definitions/veza-backend-api_internal_handlers.APIResponse'
"403":
description: No permission
schema:
$ref: '#/definitions/veza-backend-api_internal_handlers.APIResponse'
"404":
description: Track or file not found
schema:
$ref: '#/definitions/veza-backend-api_internal_handlers.APIResponse'
"500":
description: Internal Error
schema:
$ref: '#/definitions/veza-backend-api_internal_handlers.APIResponse'
summary: Stream a track (raw audio + Range)
tags:
- Track
/tracks/{id}/versions/{versionId}/restore:
post:
description: Rollback a track to a previous version. Only the track owner can
restore.
parameters:
- description: Track UUID
in: path
name: id
required: true
type: string
- description: Version UUID
in: path
name: versionId
required: true
type: string
produces:
- application/json
responses:
"200":
description: OK
schema:
allOf:
- $ref: '#/definitions/veza-backend-api_internal_handlers.APIResponse'
- properties:
data:
properties:
message:
type: string
type: object
type: object
"400":
description: Invalid id
schema:
$ref: '#/definitions/veza-backend-api_internal_handlers.APIResponse'
"401":
description: Unauthorized
schema:
$ref: '#/definitions/veza-backend-api_internal_handlers.APIResponse'
"403":
description: Not owner
schema:
$ref: '#/definitions/veza-backend-api_internal_handlers.APIResponse'
"404":
description: Track or version not found
schema:
$ref: '#/definitions/veza-backend-api_internal_handlers.APIResponse'
"500":
description: Internal Error
schema:
$ref: '#/definitions/veza-backend-api_internal_handlers.APIResponse'
security:
- BearerAuth: []
summary: Restore track version
tags:
- Track
/tracks/{id}/waveform:
get:
description: Returns a JSON peaks array used by the client to draw the audio
waveform preview. 404 if waveform extraction is not complete yet.
parameters:
- description: Track UUID
in: path
name: id
required: true
type: string
produces:
- application/json
responses:
"200":
description: Waveform peaks JSON (tool-specific shape)
schema:
type: object
"400":
description: Invalid track id
schema:
$ref: '#/definitions/veza-backend-api_internal_handlers.APIResponse'
"404":
description: Waveform not generated / track not found
schema:
$ref: '#/definitions/veza-backend-api_internal_handlers.APIResponse'
"500":
description: Internal Error
schema:
$ref: '#/definitions/veza-backend-api_internal_handlers.APIResponse'
summary: Get track waveform
tags:
- Track
/tracks/batch/delete:
post:
consumes:
- application/json
description: Soft-delete up to N tracks in one request. Per-track ownership
checked (admin can delete others).
parameters:
- description: List of track UUIDs
in: body
name: request
required: true
schema:
$ref: '#/definitions/internal_core_track.BatchDeleteRequest'
produces:
- application/json
responses:
"200":
description: OK
schema:
allOf:
- $ref: '#/definitions/veza-backend-api_internal_response.APIResponse'
- properties:
data:
properties:
deleted:
items:
type: string
type: array
failed:
items:
type: object
type: array
type: object
type: object
"400":
description: Validation / batch size exceeded
schema:
$ref: '#/definitions/veza-backend-api_internal_response.APIResponse'
"401":
description: Unauthorized
schema:
$ref: '#/definitions/veza-backend-api_internal_response.APIResponse'
"500":
description: Internal Error
schema:
$ref: '#/definitions/veza-backend-api_internal_response.APIResponse'
security:
- BearerAuth: []
summary: Batch delete tracks
tags:
- Track
/tracks/batch/update:
post:
consumes:
- application/json
description: Apply a partial metadata update to up to N tracks in one request.
Per-track ownership checked.
parameters:
- description: Track UUIDs + shared updates map
in: body
name: request
required: true
schema:
$ref: '#/definitions/internal_core_track.BatchUpdateRequest'
produces:
- application/json
responses:
"200":
description: OK
schema:
allOf:
- $ref: '#/definitions/veza-backend-api_internal_response.APIResponse'
- properties:
data:
properties:
failed:
items:
type: object
type: array
updated:
items:
type: string
type: array
type: object
type: object
"400":
description: Validation / batch size exceeded
schema:
$ref: '#/definitions/veza-backend-api_internal_response.APIResponse'
"401":
description: Unauthorized
schema:
$ref: '#/definitions/veza-backend-api_internal_response.APIResponse'
"500":
description: Internal Error
schema:
$ref: '#/definitions/veza-backend-api_internal_response.APIResponse'
security:
- BearerAuth: []
summary: Batch update tracks
tags:
- Track
/tracks/chunk:
post:
consumes:
- multipart/form-data
description: Upload a single chunk of a file
parameters:
- description: Chunk Data
in: formData
name: chunk
required: true
type: file
- description: Upload ID
in: formData
name: upload_id
required: true
type: string
- description: Chunk Number
in: formData
name: chunk_number
required: true
type: integer
- description: Total Chunks
in: formData
name: total_chunks
required: true
type: integer
- description: Total Size
format: int64
in: formData
name: total_size
required: true
type: integer
- description: Filename
in: formData
name: filename
required: true
type: string
produces:
- application/json
responses:
"200":
description: OK
schema:
allOf:
- $ref: '#/definitions/veza-backend-api_internal_response.APIResponse'
- properties:
data:
properties:
message:
type: string
progress:
format: float64
type: number
received_chunks:
type: integer
upload_id:
type: string
type: object
type: object
"400":
description: Validation Error
schema:
$ref: '#/definitions/veza-backend-api_internal_response.APIResponse'
"401":
description: Unauthorized
schema:
$ref: '#/definitions/veza-backend-api_internal_response.APIResponse'
security:
- BearerAuth: []
summary: Upload Chunk
tags:
- Track
/tracks/complete:
post:
consumes:
- application/json
description: Finish upload session and assemble file
parameters:
- description: Upload ID
in: body
name: request
required: true
schema:
$ref: '#/definitions/internal_core_track.CompleteChunkedUploadRequest'
produces:
- application/json
responses:
"201":
description: Created
schema:
allOf:
- $ref: '#/definitions/veza-backend-api_internal_response.APIResponse'
- properties:
data:
properties:
md5:
type: string
message:
type: string
track:
$ref: '#/definitions/veza-backend-api_internal_models.Track'
type: object
type: object
"400":
description: Validation or Assemblage Error
schema:
$ref: '#/definitions/veza-backend-api_internal_response.APIResponse'
"401":
description: Unauthorized
schema:
$ref: '#/definitions/veza-backend-api_internal_response.APIResponse'
security:
- BearerAuth: []
summary: Complete Chunked Upload
tags:
- Track
/tracks/initiate:
post:
consumes:
- application/json
description: Start a new chunked upload session
parameters:
- description: Upload Metadata
in: body
name: request
required: true
schema:
$ref: '#/definitions/internal_core_track.InitiateChunkedUploadRequest'
produces:
- application/json
responses:
"200":
description: OK
schema:
allOf:
- $ref: '#/definitions/veza-backend-api_internal_response.APIResponse'
- properties:
data:
properties:
message:
type: string
upload_id:
type: string
type: object
type: object
"400":
description: Validation Error
schema:
$ref: '#/definitions/veza-backend-api_internal_response.APIResponse'
"401":
description: Unauthorized
schema:
$ref: '#/definitions/veza-backend-api_internal_response.APIResponse'
security:
- BearerAuth: []
summary: Initiate Chunked Upload
tags:
- Track
/tracks/quota/{id}:
get:
consumes:
- application/json
description: Get remaining upload quota for the user
parameters:
- description: User ID or 'me' for current user
in: path
name: id
required: true
type: string
produces:
- application/json
responses:
"200":
description: OK
schema:
allOf:
- $ref: '#/definitions/veza-backend-api_internal_response.APIResponse'
- properties:
data:
properties:
quota:
type: object
type: object
type: object
"401":
description: Unauthorized
schema:
$ref: '#/definitions/veza-backend-api_internal_response.APIResponse'
"403":
description: Forbidden
schema:
$ref: '#/definitions/veza-backend-api_internal_response.APIResponse'
security:
- BearerAuth: []
summary: Get Upload Quota
tags:
- Track
/tracks/recommendations:
get:
description: Personalized tracks for D2 autoplay. If seed_track_id is given,
returns tracks similar to that seed. Otherwise, uses the caller's history
(chronological, no behavioural ranking — CLAUDE.md rule 7).
parameters:
- default: 20
description: Max items (max 100)
in: query
name: limit
type: integer
- description: Start from this track's similarity neighbours
in: query
name: seed_track_id
type: string
produces:
- application/json
responses:
"200":
description: OK
schema:
allOf:
- $ref: '#/definitions/veza-backend-api_internal_response.APIResponse'
- properties:
data:
properties:
tracks:
items:
$ref: '#/definitions/veza-backend-api_internal_models.Track'
type: array
type: object
type: object
"500":
description: Internal Error
schema:
$ref: '#/definitions/veza-backend-api_internal_response.APIResponse'
security:
- BearerAuth: []
summary: Get track recommendations
tags:
- Track
/tracks/resume/{uploadId}:
get:
consumes:
- application/json
description: Get state of an interrupted upload
parameters:
- description: Upload ID
in: path
name: uploadId
required: true
type: string
produces:
- application/json
responses:
"200":
description: OK
schema:
allOf:
- $ref: '#/definitions/veza-backend-api_internal_response.APIResponse'
- properties:
data:
properties:
chunks_received:
type: integer
upload_id:
type: string
type: object
type: object
"404":
description: Upload session not found
schema:
$ref: '#/definitions/veza-backend-api_internal_response.APIResponse'
security:
- BearerAuth: []
summary: Resume Upload
tags:
- Track
/tracks/search:
get:
description: Full-text + faceted search on tracks (genre, BPM, duration, tags,
musical key, dates). Sort-by and order configurable.
parameters:
- description: Full-text query (title/artist/album)
in: query
name: q
type: string
- description: Comma-separated tag list
in: query
name: tags
type: string
- default: OR
description: Tag combinator (OR / AND)
in: query
name: tag_mode
type: string
- description: Minimum duration (seconds)
in: query
name: min_duration
type: integer
- description: Maximum duration (seconds)
in: query
name: max_duration
type: integer
- description: Minimum BPM
in: query
name: min_bpm
type: integer
- description: Maximum BPM
in: query
name: max_bpm
type: integer
- description: Genre filter
in: query
name: genre
type: string
- description: Audio format filter
in: query
name: format
type: string
- description: Musical key filter
in: query
name: musical_key
type: string
- description: Created-after (RFC3339)
in: query
name: min_date
type: string
- description: Created-before (RFC3339)
in: query
name: max_date
type: string
- default: 1
description: Page (1-based)
in: query
name: page
type: integer
- default: 20
description: Items per page (max 100)
in: query
name: limit
type: integer
- default: created_at
description: Sort column
in: query
name: sort_by
type: string
- default: desc
description: asc / desc
in: query
name: sort_order
type: string
produces:
- application/json
responses:
"200":
description: OK
schema:
allOf:
- $ref: '#/definitions/veza-backend-api_internal_response.APIResponse'
- properties:
data:
properties:
pagination:
type: object
tracks:
items:
$ref: '#/definitions/veza-backend-api_internal_models.Track'
type: array
type: object
type: object
"500":
description: Internal Error
schema:
$ref: '#/definitions/veza-backend-api_internal_response.APIResponse'
summary: Advanced track search
tags:
- Track
/tracks/share/{id}:
delete:
description: Permanently disable a share token. Only the share issuer (or admin)
can revoke.
parameters:
- description: Share UUID
in: path
name: id
required: true
type: string
produces:
- application/json
responses:
"200":
description: OK
schema:
allOf:
- $ref: '#/definitions/veza-backend-api_internal_handlers.APIResponse'
- properties:
data:
properties:
message:
type: string
type: object
type: object
"400":
description: Validation
schema:
$ref: '#/definitions/veza-backend-api_internal_handlers.APIResponse'
"401":
description: Unauthorized
schema:
$ref: '#/definitions/veza-backend-api_internal_handlers.APIResponse'
"403":
description: Not issuer
schema:
$ref: '#/definitions/veza-backend-api_internal_handlers.APIResponse'
"404":
description: Share not found
schema:
$ref: '#/definitions/veza-backend-api_internal_handlers.APIResponse'
"500":
description: Internal Error
schema:
$ref: '#/definitions/veza-backend-api_internal_handlers.APIResponse'
security:
- BearerAuth: []
summary: Revoke share link
tags:
- Track
/tracks/shared/{token}:
get:
description: Public endpoint that resolves a share token and returns the track
+ share metadata. No auth required; the token IS the auth.
parameters:
- description: Opaque share token issued by CreateShare
in: path
name: token
required: true
type: string
produces:
- application/json
responses:
"200":
description: OK
schema:
allOf:
- $ref: '#/definitions/veza-backend-api_internal_handlers.APIResponse'
- properties:
data:
properties:
share:
type: object
track:
$ref: '#/definitions/veza-backend-api_internal_models.Track'
type: object
type: object
"400":
description: Missing token
schema:
$ref: '#/definitions/veza-backend-api_internal_handlers.APIResponse'
"403":
description: Share link expired
schema:
$ref: '#/definitions/veza-backend-api_internal_handlers.APIResponse'
"404":
description: Share or track not found
schema:
$ref: '#/definitions/veza-backend-api_internal_handlers.APIResponse'
"500":
description: Internal Error
schema:
$ref: '#/definitions/veza-backend-api_internal_handlers.APIResponse'
summary: Get track by share token
tags:
- Track
/tracks/suggested-tags:
get:
description: Returns a static tag suggestion list for a genre — useful for upload
autocomplete and filter chips.
parameters:
- default: default
description: Genre slug (pop, rock, electronic, hip-hop, jazz, classical,
ambient, default)
in: query
name: genre
type: string
produces:
- application/json
responses:
"200":
description: OK
schema:
allOf:
- $ref: '#/definitions/veza-backend-api_internal_response.APIResponse'
- properties:
data:
properties:
tags:
items:
type: string
type: array
type: object
type: object
summary: Get suggested tags
tags:
- Track
/users:
get:
consumes:
- application/json
description: Get a paginated list of users with optional filtering
parameters:
- default: 1
description: Page number
in: query
name: page
type: integer
- default: 20
description: Items per page
in: query
name: limit
type: integer
- description: Filter by role
in: query
name: role
type: string
- description: Filter by active status
in: query
name: is_active
type: boolean
- description: Filter by verified status
in: query
name: is_verified
type: boolean
- description: Search by username, email, first_name, last_name
in: query
name: search
type: string
- default: created_at
description: Sort field (created_at, username, email, last_login_at)
in: query
name: sort_by
type: string
- default: desc
description: Sort order (asc, desc)
in: query
name: sort_order
type: string
produces:
- application/json
responses:
"200":
description: OK
schema:
allOf:
- $ref: '#/definitions/internal_handlers.APIResponse'
- properties:
data:
properties:
pagination:
type: object
users:
type: array
type: object
type: object
"500":
description: Internal Error
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
summary: List Users
tags:
- User
/users/{id}:
delete:
consumes:
- application/json
description: Soft delete a user (only user owner or admin can delete)
parameters:
- description: User ID
in: path
name: id
required: true
type: string
produces:
- application/json
responses:
"200":
description: User deleted successfully
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
"400":
description: Invalid ID
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
"401":
description: Unauthorized
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
"403":
description: Forbidden - Not user owner or admin
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
"404":
description: User not found
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
security:
- BearerAuth: []
summary: Delete user
tags:
- User
get:
consumes:
- application/json
description: Get public profile information for a user
parameters:
- description: User ID
in: path
name: id
required: true
type: string
produces:
- application/json
responses:
"200":
description: OK
schema:
allOf:
- $ref: '#/definitions/internal_handlers.APIResponse'
- properties:
data:
properties:
profile:
type: object
type: object
type: object
"400":
description: Invalid ID
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
"404":
description: User not found
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
summary: Get Profile by ID
tags:
- User
put:
consumes:
- application/json
description: Update user profile details
parameters:
- description: User ID
in: path
name: id
required: true
type: string
- description: Profile Data
in: body
name: profile
required: true
schema:
$ref: '#/definitions/internal_handlers.UpdateProfileRequest'
produces:
- application/json
responses:
"200":
description: OK
schema:
allOf:
- $ref: '#/definitions/internal_handlers.APIResponse'
- properties:
data:
properties:
profile:
type: object
type: object
type: object
"400":
description: Validation Error
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
"401":
description: Unauthorized
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
"403":
description: Forbidden
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
security:
- BearerAuth: []
summary: Update Profile
tags:
- User
/users/{id}/block:
delete:
description: Authenticated user unblocks target user (idempotent).
parameters:
- description: Target user UUID
in: path
name: id
required: true
type: string
produces:
- application/json
responses:
"200":
description: OK
schema:
allOf:
- $ref: '#/definitions/internal_handlers.APIResponse'
- properties:
data:
properties:
message:
type: string
type: object
type: object
"400":
description: Invalid id
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
"401":
description: Unauthorized
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
"500":
description: Internal Error
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
security:
- BearerAuth: []
summary: Unblock user
tags:
- User
post:
description: Authenticated user blocks target user (hides their content, prevents
follows). Cannot self-block.
parameters:
- description: Target user UUID
in: path
name: id
required: true
type: string
produces:
- application/json
responses:
"200":
description: OK
schema:
allOf:
- $ref: '#/definitions/internal_handlers.APIResponse'
- properties:
data:
properties:
message:
type: string
type: object
type: object
"400":
description: Validation / self-block
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
"401":
description: Unauthorized
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
"500":
description: Internal Error
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
security:
- BearerAuth: []
summary: Block user
tags:
- User
/users/{id}/completion:
get:
consumes:
- application/json
description: Get profile completion percentage and missing fields
parameters:
- description: User ID
in: path
name: id
required: true
type: string
produces:
- application/json
responses:
"200":
description: OK
schema:
allOf:
- $ref: '#/definitions/internal_handlers.APIResponse'
- properties:
data:
type: object
type: object
"400":
description: Invalid ID
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
"401":
description: Unauthorized
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
"403":
description: Forbidden
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
summary: Get Profile Completion
tags:
- User
/users/{id}/follow:
delete:
description: Authenticated user stops following target user (idempotent).
parameters:
- description: Target user UUID
in: path
name: id
required: true
type: string
produces:
- application/json
responses:
"200":
description: OK
schema:
allOf:
- $ref: '#/definitions/internal_handlers.APIResponse'
- properties:
data:
properties:
message:
type: string
type: object
type: object
"400":
description: Invalid id
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
"401":
description: Unauthorized
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
"500":
description: Internal Error
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
security:
- BearerAuth: []
summary: Unfollow user
tags:
- User
post:
description: Authenticated user follows target user. Creates a notification
(F554 grouped) for the target.
parameters:
- description: Target user UUID
in: path
name: id
required: true
type: string
produces:
- application/json
responses:
"200":
description: OK
schema:
allOf:
- $ref: '#/definitions/internal_handlers.APIResponse'
- properties:
data:
properties:
message:
type: string
type: object
type: object
"400":
description: Invalid id
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
"401":
description: Unauthorized
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
"404":
description: User not found
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
"500":
description: Internal Error
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
security:
- BearerAuth: []
summary: Follow user
tags:
- User
/users/{id}/likes:
get:
description: Returns paginated tracks the given user has liked. Used for profile
"Likes" tab.
parameters:
- description: User UUID
in: path
name: id
required: true
type: string
- default: 20
description: Items per page (max 100)
in: query
name: limit
type: integer
- default: 0
description: Offset for pagination
in: query
name: offset
type: integer
produces:
- application/json
responses:
"200":
description: OK
schema:
allOf:
- $ref: '#/definitions/veza-backend-api_internal_handlers.APIResponse'
- properties:
data:
properties:
limit:
type: integer
offset:
type: integer
total:
type: integer
tracks:
items:
$ref: '#/definitions/veza-backend-api_internal_models.Track'
type: array
type: object
type: object
"400":
description: Validation
schema:
$ref: '#/definitions/veza-backend-api_internal_handlers.APIResponse'
"401":
description: Unauthorized
schema:
$ref: '#/definitions/veza-backend-api_internal_handlers.APIResponse'
"500":
description: Internal Error
schema:
$ref: '#/definitions/veza-backend-api_internal_handlers.APIResponse'
security:
- BearerAuth: []
summary: List tracks liked by a user
tags:
- User
/users/{id}/reposts:
get:
description: Returns paginated tracks the user has reposted. Used for profile
"Reposts" tab.
parameters:
- description: User UUID
in: path
name: id
required: true
type: string
- default: 20
description: Items per page (max 100)
in: query
name: limit
type: integer
- default: 0
description: Offset for pagination
in: query
name: offset
type: integer
produces:
- application/json
responses:
"200":
description: OK
schema:
allOf:
- $ref: '#/definitions/veza-backend-api_internal_handlers.APIResponse'
- properties:
data:
properties:
limit:
type: integer
offset:
type: integer
total:
type: integer
tracks:
items:
$ref: '#/definitions/veza-backend-api_internal_models.Track'
type: array
type: object
type: object
"400":
description: Validation
schema:
$ref: '#/definitions/veza-backend-api_internal_handlers.APIResponse'
"500":
description: Internal Error
schema:
$ref: '#/definitions/veza-backend-api_internal_handlers.APIResponse'
summary: List tracks reposted by a user
tags:
- User
/users/by-username/{username}:
get:
consumes:
- application/json
description: Get public profile information for a user by username
parameters:
- description: Username
in: path
name: username
required: true
type: string
produces:
- application/json
responses:
"200":
description: OK
schema:
allOf:
- $ref: '#/definitions/internal_handlers.APIResponse'
- properties:
data:
properties:
profile:
type: object
type: object
type: object
"400":
description: Missing username
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
"404":
description: User not found
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
summary: Get Profile by Username
tags:
- User
/users/me:
delete:
description: Permanently delete user account with anonymization, session revocation,
audit log
parameters:
- description: Password, reason, confirm_text (must be DELETE)
in: body
name: body
required: true
schema:
$ref: '#/definitions/internal_handlers.DeleteAccountRequest'
responses:
"200":
description: OK
schema:
additionalProperties: true
type: object
"400":
description: Bad Request
schema:
additionalProperties: true
type: object
"401":
description: Unauthorized
schema:
additionalProperties: true
type: object
"500":
description: Internal Server Error
schema:
additionalProperties: true
type: object
security:
- BearerAuth: []
summary: Delete account
tags:
- Users
/users/me/privacy/opt-out:
post:
description: Saves the user's Do Not Sell preference (CCPA compliance)
responses:
"200":
description: OK
schema:
additionalProperties: true
type: object
"401":
description: Unauthorized
schema:
additionalProperties: true
type: object
"500":
description: Internal Server Error
schema:
additionalProperties: true
type: object
security:
- BearerAuth: []
summary: CCPA Do Not Sell opt-out
tags:
- Users
/users/search:
get:
description: Full-text search on users (username, display_name). Paginated.
Public.
parameters:
- description: Full-text query
in: query
name: q
type: string
- default: 1
description: Page
in: query
name: page
type: integer
- default: 20
description: Items per page (max 100)
in: query
name: limit
type: integer
produces:
- application/json
responses:
"200":
description: OK
schema:
allOf:
- $ref: '#/definitions/internal_handlers.APIResponse'
- properties:
data:
properties:
pagination:
type: object
users:
items:
$ref: '#/definitions/veza-backend-api_internal_models.User'
type: array
type: object
type: object
"400":
description: Validation (bounds)
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
"500":
description: Internal Error
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
summary: Search users
tags:
- User
/users/suggestions:
get:
description: Returns suggested users to follow for the authenticated user. Declarative
discovery — no behavioural scoring (CLAUDE.md rule 7).
parameters:
- default: 10
description: Max items (max 50)
in: query
name: limit
type: integer
produces:
- application/json
responses:
"200":
description: OK
schema:
allOf:
- $ref: '#/definitions/internal_handlers.APIResponse'
- properties:
data:
properties:
users:
items:
$ref: '#/definitions/veza-backend-api_internal_models.User'
type: array
type: object
type: object
"401":
description: Unauthorized
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
"500":
description: Internal Error
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
security:
- BearerAuth: []
summary: Get follow suggestions
tags:
- User
/validate:
post:
consumes:
- application/json
description: Validates request data against known DTO types without executing
the actual operation
parameters:
- description: Validation request with type and data
in: body
name: request
required: true
schema:
$ref: '#/definitions/internal_handlers.ValidateRequest'
produces:
- application/json
responses:
"200":
description: Validation result
schema:
$ref: '#/definitions/internal_handlers.ValidateResponse'
"400":
description: Invalid request format
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
summary: Validate request body
tags:
- Validation
/webhooks:
get:
consumes:
- application/json
description: Get a list of all webhooks registered by the current user
produces:
- application/json
responses:
"200":
description: OK
schema:
allOf:
- $ref: '#/definitions/internal_handlers.APIResponse'
- properties:
data:
properties:
webhooks:
type: array
type: object
type: object
"401":
description: Unauthorized
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
"500":
description: Internal server error
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
security:
- BearerAuth: []
summary: List webhooks
tags:
- Webhook
post:
consumes:
- application/json
description: Register a new webhook for receiving events
parameters:
- description: Webhook registration data
in: body
name: webhook
required: true
schema:
type: object
produces:
- application/json
responses:
"201":
description: Created
schema:
allOf:
- $ref: '#/definitions/internal_handlers.APIResponse'
- properties:
data:
properties:
webhook:
type: object
type: object
type: object
"400":
description: Validation error
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
"401":
description: Unauthorized
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
"500":
description: Internal server error
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
security:
- BearerAuth: []
summary: Register webhook
tags:
- Webhook
/webhooks/{id}:
delete:
consumes:
- application/json
description: Delete a webhook by ID
parameters:
- description: Webhook ID
in: path
name: id
required: true
type: string
produces:
- application/json
responses:
"200":
description: OK
schema:
allOf:
- $ref: '#/definitions/internal_handlers.APIResponse'
- properties:
data:
properties:
message:
type: string
type: object
type: object
"400":
description: Invalid webhook ID
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
"401":
description: Unauthorized
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
"404":
description: Webhook not found
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
security:
- BearerAuth: []
summary: Delete webhook
tags:
- Webhook
/webhooks/{id}/regenerate-key:
post:
consumes:
- application/json
description: Generate a new API key for a webhook (invalidates the old one)
parameters:
- description: Webhook ID
in: path
name: id
required: true
type: string
produces:
- application/json
responses:
"200":
description: OK
schema:
allOf:
- $ref: '#/definitions/internal_handlers.APIResponse'
- properties:
data:
properties:
api_key:
type: string
message:
type: string
type: object
type: object
"400":
description: Invalid webhook ID
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
"401":
description: Unauthorized
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
"404":
description: Webhook not found
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
"500":
description: Internal server error
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
security:
- BearerAuth: []
summary: Regenerate webhook API key
tags:
- Webhook
/webhooks/{id}/test:
post:
consumes:
- application/json
description: Send a test event to a webhook to verify it's working
parameters:
- description: Webhook ID
in: path
name: id
required: true
type: string
produces:
- application/json
responses:
"200":
description: OK
schema:
allOf:
- $ref: '#/definitions/internal_handlers.APIResponse'
- properties:
data:
properties:
message:
type: string
type: object
type: object
"400":
description: Invalid webhook ID
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
"401":
description: Unauthorized
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
"404":
description: Webhook not found
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
security:
- BearerAuth: []
summary: Test webhook
tags:
- Webhook
/webhooks/stats:
get:
consumes:
- application/json
description: Get statistics for webhook delivery and performance
produces:
- application/json
responses:
"200":
description: OK
schema:
allOf:
- $ref: '#/definitions/internal_handlers.APIResponse'
- properties:
data:
properties:
stats:
type: object
type: object
type: object
"401":
description: Unauthorized
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
"500":
description: Internal server error
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
security:
- BearerAuth: []
summary: Get webhook statistics
tags:
- Webhook
securityDefinitions:
ApiKeyAuth:
description: 'Developer API key (obtain from Developer Portal). Format: vza_xxxxx'
in: header
name: X-API-Key
type: apiKey
BearerAuth:
in: header
name: Authorization
type: apiKey
swagger: "2.0"