openapi: 3.1.0
info:
  title: Sewapedia API
  version: 1.0.0
  description: "REST API platform rental aset bergerak multi-vendor. All responses use { success, data | error } envelope.
    AI agents: see /llms.txt and docs/API_AGENT_GUIDE.md."
servers:
  - url: /api/v1
tags:
  - name: platform
    description: Health & public config
  - name: auth
    description: JWT login, refresh, API keys
  - name: catalog
    description: Assets, categories, vendors
  - name: booking
    description: Rental requests & lifecycle
  - name: payment
    description: Midtrans, credit, webhooks
  - name: trust
    description: Verification & risk
  - name: owner
    description: Vendor/owner operations
  - name: admin
    description: Admin-only (RBAC ADMIN)
  - name: pricing
    description: Price quotes
  - name: ucp
    description: Universal Commerce Protocol facade
  - name: mcp
    description: Hosted Model Context Protocol (Streamable HTTP) — see /mcp-agent-guide.md
  - name: notifications
    description: In-app & push
  - name: reviews
    description: Booking reviews
  - name: chat
    description: Booking chat (prefer polling over SSE for agents)
  - name: user
    description: User profile
  - name: internal
    description: Cron — not for public agents
paths:
  /health:
    get:
      tags:
        - platform
      summary: Health check
      operationId: platform_list_health
      responses:
        "200": &a1
          description: Success envelope
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ApiSuccess"
          headers:
            X-RateLimit-Limit:
              schema:
                type: integer
              description: Rate limit ceiling
            X-RateLimit-Remaining:
              schema:
                type: integer
              description: Remaining requests in window
        "201": *a1
        "400": &a2
          description: Error envelope
          content: &a3
            application/json:
              schema:
                $ref: "#/components/schemas/ApiError"
        "401": *a2
        "403": *a2
        "404": *a2
        "429":
          description: Rate limited — check Retry-After and X-RateLimit-* headers
          content: *a3
  /assets:
    get:
      tags:
        - catalog
      summary: List aset (q, category, vendorSlug, city, minPrice, maxPrice, page, limit)
      operationId: catalog_list_assets
      responses:
        "200": *a1
        "201": *a1
        "400": *a2
        "401": *a2
        "403": *a2
        "404": *a2
        "429":
          description: Rate limited — check Retry-After and X-RateLimit-* headers
          content: *a3
  /assets/{slug}:
    get:
      tags:
        - catalog
      summary: Detail aset
      operationId: catalog_get_assets
      responses:
        "200": *a1
        "201": *a1
        "400": *a2
        "401": *a2
        "403": *a2
        "404": *a2
        "429":
          description: Rate limited — check Retry-After and X-RateLimit-* headers
          content: *a3
  /assets/{slug}/availability:
    get:
      tags:
        - catalog
      summary: Ketersediaan kalender (from, to ISO date)
      operationId: catalog_get_assets_by_id_availability
      responses:
        "200": *a1
        "201": *a1
        "400": *a2
        "401": *a2
        "403": *a2
        "404": *a2
        "429":
          description: Rate limited — check Retry-After and X-RateLimit-* headers
          content: *a3
  /catalog/feed:
    get:
      tags:
        - platform
      summary: Feed katalog paginated untuk agent discovery
      operationId: platform_get_catalog_feed
      responses:
        "200": *a1
        "201": *a1
        "400": *a2
        "401": *a2
        "403": *a2
        "404": *a2
        "429":
          description: Rate limited — check Retry-After and X-RateLimit-* headers
          content: *a3
  /ucp/products:
    get:
      tags:
        - ucp
      summary: UCP product discovery (search/feed)
      operationId: ucp_get_ucp_products
      responses:
        "200": *a1
        "201": *a1
        "400": *a2
        "401": *a2
        "403": *a2
        "404": *a2
        "429":
          description: Rate limited — check Retry-After and X-RateLimit-* headers
          content: *a3
  /ucp/products/{slug}:
    get:
      tags:
        - ucp
      summary: UCP product lookup by slug
      operationId: ucp_get_ucp_products
      responses:
        "200": *a1
        "201": *a1
        "400": *a2
        "401": *a2
        "403": *a2
        "404": *a2
        "429":
          description: Rate limited — check Retry-After and X-RateLimit-* headers
          content: *a3
  /ucp/products/{slug}/availability:
    get:
      tags:
        - ucp
      summary: UCP product availability (from, to)
      operationId: ucp_get_ucp_products_by_id_availability
      responses:
        "200": *a1
        "201": *a1
        "400": *a2
        "401": *a2
        "403": *a2
        "404": *a2
        "429":
          description: Rate limited — check Retry-After and X-RateLimit-* headers
          content: *a3
  /ucp/quotes:
    post:
      tags:
        - ucp
      summary: UCP price quote
      operationId: ucp_create_ucp_quotes
      responses:
        "200": *a1
        "201": *a1
        "400": *a2
        "401": *a2
        "403": *a2
        "404": *a2
        "429":
          description: Rate limited — check Retry-After and X-RateLimit-* headers
          content: *a3
  /ucp/checkout/sessions:
    post:
      tags:
        - ucp
      summary: UCP checkout session create (booking)
      operationId: ucp_create_ucp_checkout_sessions
      security:
        - BearerAuth: []
      responses:
        "200": *a1
        "201": *a1
        "400": *a2
        "401": *a2
        "403": *a2
        "404": *a2
        "429":
          description: Rate limited — check Retry-After and X-RateLimit-* headers
          content: *a3
  /ucp/checkout/sessions/{id}:
    get:
      tags:
        - ucp
      summary: UCP checkout session status
      operationId: ucp_get_ucp_checkout_sessions
      security:
        - BearerAuth: []
      responses:
        "200": *a1
        "201": *a1
        "400": *a2
        "401": *a2
        "403": *a2
        "404": *a2
        "429":
          description: Rate limited — check Retry-After and X-RateLimit-* headers
          content: *a3
  /ucp/checkout/sessions/{id}/complete:
    post:
      tags:
        - ucp
      summary: UCP complete checkout (promote or pay)
      operationId: ucp_create_ucp_checkout_sessions_by_id_complete
      security:
        - BearerAuth: []
      responses:
        "200": *a1
        "201": *a1
        "400": *a2
        "401": *a2
        "403": *a2
        "404": *a2
        "429":
          description: Rate limited — check Retry-After and X-RateLimit-* headers
          content: *a3
  /ucp/webhooks:
    get:
      tags:
        - ucp
      summary: UCP list order status webhooks
      operationId: ucp_get_ucp_webhooks
      security:
        - BearerAuth: []
      responses:
        "200": *a1
        "201": *a1
        "400": *a2
        "401": *a2
        "403": *a2
        "404": *a2
        "429":
          description: Rate limited — check Retry-After and X-RateLimit-* headers
          content: *a3
    post:
      tags:
        - ucp
      summary: UCP register order status webhook
      operationId: ucp_create_ucp_webhooks
      security:
        - BearerAuth: []
      responses:
        "200": *a1
        "201": *a1
        "400": *a2
        "401": *a2
        "403": *a2
        "404": *a2
        "429":
          description: Rate limited — check Retry-After and X-RateLimit-* headers
          content: *a3
  /categories:
    get:
      tags:
        - catalog
      summary: Daftar kategori
      operationId: catalog_list_categories
      responses:
        "200": *a1
        "201": *a1
        "400": *a2
        "401": *a2
        "403": *a2
        "404": *a2
        "429":
          description: Rate limited — check Retry-After and X-RateLimit-* headers
          content: *a3
  /assets/{slug}/inquiry/messages:
    get:
      tags:
        - catalog
      summary: Chat inquiry pra-booking (list / buat thread)
      operationId: catalog_get_assets_by_id_inquiry_messages
      responses:
        "200": *a1
        "201": *a1
        "400": *a2
        "401": *a2
        "403": *a2
        "404": *a2
        "429":
          description: Rate limited — check Retry-After and X-RateLimit-* headers
          content: *a3
    post:
      tags:
        - catalog
      summary: Kirim pesan inquiry pra-booking
      operationId: catalog_create_assets_by_id_inquiry_messages
      responses:
        "200": *a1
        "201": *a1
        "400": *a2
        "401": *a2
        "403": *a2
        "404": *a2
        "429":
          description: Rate limited — check Retry-After and X-RateLimit-* headers
          content: *a3
  /assets/{slug}/inquiry/stream:
    get:
      tags:
        - catalog
      summary: SSE inquiry chat stream
      operationId: catalog_get_assets_by_id_inquiry_stream
      responses:
        "200": *a1
        "201": *a1
        "400": *a2
        "401": *a2
        "403": *a2
        "404": *a2
        "429":
          description: Rate limited — check Retry-After and X-RateLimit-* headers
          content: *a3
  /auth/register:
    post:
      tags:
        - auth
      summary: Registrasi customer/vendor
      operationId: auth_register_auth_register
      responses:
        "200": *a1
        "201": *a1
        "400": *a2
        "401": *a2
        "403": *a2
        "404": *a2
        "429":
          description: Rate limited — check Retry-After and X-RateLimit-* headers
          content: *a3
  /auth/login:
    post:
      tags:
        - auth
      summary: Login JWT (email + password)
      operationId: auth_login
      responses:
        "200": *a1
        "201": *a1
        "400": *a2
        "401": *a2
        "403": *a2
        "404": *a2
        "429":
          description: Rate limited — check Retry-After and X-RateLimit-* headers
          content: *a3
  /auth/refresh:
    post:
      tags:
        - auth
      summary: Rotasi refresh token
      operationId: auth_create_auth_refresh
      responses:
        "200": *a1
        "201": *a1
        "400": *a2
        "401": *a2
        "403": *a2
        "404": *a2
        "429":
          description: Rate limited — check Retry-After and X-RateLimit-* headers
          content: *a3
  /auth/logout:
    post:
      tags:
        - auth
      summary: Revoke refresh token
      operationId: auth_create_auth_logout
      responses:
        "200": *a1
        "201": *a1
        "400": *a2
        "401": *a2
        "403": *a2
        "404": *a2
        "429":
          description: Rate limited — check Retry-After and X-RateLimit-* headers
          content: *a3
  /auth/forgot-password:
    post:
      tags:
        - auth
      summary: Lupa password — kirim email reset
      operationId: auth_create_auth_forgot-password
      responses:
        "200": *a1
        "201": *a1
        "400": *a2
        "401": *a2
        "403": *a2
        "404": *a2
        "429":
          description: Rate limited — check Retry-After and X-RateLimit-* headers
          content: *a3
  /auth/reset-password:
    post:
      tags:
        - auth
      summary: Reset password via token email
      operationId: auth_create_auth_reset-password
      responses:
        "200": *a1
        "201": *a1
        "400": *a2
        "401": *a2
        "403": *a2
        "404": *a2
        "429":
          description: Rate limited — check Retry-After and X-RateLimit-* headers
          content: *a3
  /vendor/activate:
    post:
      tags:
        - user
      summary: Upgrade penyewa menjadi pemilik aset
      operationId: user_create_vendor_activate
      security:
        - BearerAuth: []
      responses:
        "200": *a1
        "201": *a1
        "400": *a2
        "401": *a2
        "403": *a2
        "404": *a2
        "429":
          description: Rate limited — check Retry-After and X-RateLimit-* headers
          content: *a3
  /owner/vendor-type:
    patch:
      tags:
        - owner
      summary: Ubah tipe vendor perorangan/perusahaan
      operationId: owner_update_owner_vendor-type
      security:
        - BearerAuth: []
      responses:
        "200": *a1
        "201": *a1
        "400": *a2
        "401": *a2
        "403": *a2
        "404": *a2
        "429":
          description: Rate limited — check Retry-After and X-RateLimit-* headers
          content: *a3
  /auth/otp/send:
    post:
      tags:
        - auth
      summary: Kirim OTP telepon
      operationId: auth_create_auth_otp_send
      security:
        - BearerAuth: []
      responses:
        "200": *a1
        "201": *a1
        "400": *a2
        "401": *a2
        "403": *a2
        "404": *a2
        "429":
          description: Rate limited — check Retry-After and X-RateLimit-* headers
          content: *a3
  /auth/otp/verify:
    post:
      tags:
        - auth
      summary: Verifikasi OTP
      operationId: auth_create_auth_otp_verify
      security:
        - BearerAuth: []
      responses:
        "200": *a1
        "201": *a1
        "400": *a2
        "401": *a2
        "403": *a2
        "404": *a2
        "429":
          description: Rate limited — check Retry-After and X-RateLimit-* headers
          content: *a3
  /users/me:
    get:
      tags:
        - user
      summary: Profil akun
      operationId: user_get_users_me
      security:
        - BearerAuth: []
      responses:
        "200": *a1
        "201": *a1
        "400": *a2
        "401": *a2
        "403": *a2
        "404": *a2
        "429":
          description: Rate limited — check Retry-After and X-RateLimit-* headers
          content: *a3
    patch:
      tags:
        - user
      summary: Update profil
      operationId: user_update_users_me
      security:
        - BearerAuth: []
      responses:
        "200": *a1
        "201": *a1
        "400": *a2
        "401": *a2
        "403": *a2
        "404": *a2
        "429":
          description: Rate limited — check Retry-After and X-RateLimit-* headers
          content: *a3
  /users/me/password:
    post:
      tags:
        - user
      summary: Ganti password
      operationId: user_create_users_me_password
      security:
        - BearerAuth: []
      responses:
        "200": *a1
        "201": *a1
        "400": *a2
        "401": *a2
        "403": *a2
        "404": *a2
        "429":
          description: Rate limited — check Retry-After and X-RateLimit-* headers
          content: *a3
  /verification/status:
    get:
      tags:
        - trust
      summary: Status verifikasi
      operationId: trust_get_verification_status
      security:
        - BearerAuth: []
      responses:
        "200": *a1
        "201": *a1
        "400": *a2
        "401": *a2
        "403": *a2
        "404": *a2
        "429":
          description: Rate limited — check Retry-After and X-RateLimit-* headers
          content: *a3
  /upload:
    post:
      tags:
        - trust
      summary: Upload dokumen/foto (multipart)
      operationId: trust_create_upload
      security:
        - BearerAuth: []
      responses:
        "200": *a1
        "201": *a1
        "400": *a2
        "401": *a2
        "403": *a2
        "404": *a2
        "429":
          description: Rate limited — check Retry-After and X-RateLimit-* headers
          content: *a3
  /trust-profile/me:
    get:
      tags:
        - trust
      summary: Trust profile privat
      operationId: trust_get_trust-profile_me
      security:
        - BearerAuth: []
      responses:
        "200": *a1
        "201": *a1
        "400": *a2
        "401": *a2
        "403": *a2
        "404": *a2
        "429":
          description: Rate limited — check Retry-After and X-RateLimit-* headers
          content: *a3
  /account/credit:
    get:
      tags:
        - payment
      summary: Saldo kredit penyewa dan ledger
      operationId: payment_get_account_credit
      security:
        - BearerAuth: []
      responses:
        "200": *a1
        "201": *a1
        "400": *a2
        "401": *a2
        "403": *a2
        "404": *a2
        "429":
          description: Rate limited — check Retry-After and X-RateLimit-* headers
          content: *a3
  /bookings/{id}/apply-credit:
    post:
      tags:
        - booking
      summary: Terapkan saldo kredit ke booking PENDING_PAYMENT
      operationId: booking_create_bookings_by_id_apply-credit
      security:
        - BearerAuth: []
      responses:
        "200": *a1
        "201": *a1
        "400": *a2
        "401": *a2
        "403": *a2
        "404": *a2
        "429":
          description: Rate limited — check Retry-After and X-RateLimit-* headers
          content: *a3
  /vendors/{slug}:
    get:
      tags:
        - catalog
      summary: Vendor storefront publik
      operationId: catalog_get_vendors
      responses:
        "200": *a1
        "201": *a1
        "400": *a2
        "401": *a2
        "403": *a2
        "404": *a2
        "429":
          description: Rate limited — check Retry-After and X-RateLimit-* headers
          content: *a3
  /category-requirements:
    get:
      tags:
        - catalog
      summary: Persyaratan verifikasi per kategori
      operationId: catalog_list_category-requirements
      responses:
        "200": *a1
        "201": *a1
        "400": *a2
        "401": *a2
        "403": *a2
        "404": *a2
        "429":
          description: Rate limited — check Retry-After and X-RateLimit-* headers
          content: *a3
  /trust-profile/{userId}:
    get:
      tags:
        - trust
      summary: Trust profile publik
      operationId: trust_get_trust-profile
      responses:
        "200": *a1
        "201": *a1
        "400": *a2
        "401": *a2
        "403": *a2
        "404": *a2
        "429":
          description: Rate limited — check Retry-After and X-RateLimit-* headers
          content: *a3
  /pricing/quote:
    post:
      tags:
        - pricing
      summary: Quote harga (auth opsional untuk deposit dinamis)
      operationId: pricing_create_pricing_quote
      responses:
        "200": *a1
        "201": *a1
        "400": *a2
        "401": *a2
        "403": *a2
        "404": *a2
        "429":
          description: Rate limited — check Retry-After and X-RateLimit-* headers
          content: *a3
  /risk-assess:
    post:
      tags:
        - trust
      summary: Preview risiko sebelum booking
      operationId: trust_create_risk-assess
      security:
        - BearerAuth: []
      responses:
        "200": *a1
        "201": *a1
        "400": *a2
        "401": *a2
        "403": *a2
        "404": *a2
        "429":
          description: Rate limited — check Retry-After and X-RateLimit-* headers
          content: *a3
  /bookings:
    get:
      tags:
        - booking
      summary: List booking penyewa
      operationId: booking_list_bookings
      security:
        - BearerAuth: []
      responses:
        "200": *a1
        "201": *a1
        "400": *a2
        "401": *a2
        "403": *a2
        "404": *a2
        "429":
          description: Rate limited — check Retry-After and X-RateLimit-* headers
          content: *a3
    post:
      tags:
        - booking
      summary: Buat rental request
      operationId: booking_create
      security:
        - BearerAuth: []
      responses:
        "200": *a1
        "201": *a1
        "400": *a2
        "401": *a2
        "403": *a2
        "404": *a2
        "429":
          description: Rate limited — check Retry-After and X-RateLimit-* headers
          content: *a3
  /bookings/{id}:
    get:
      tags:
        - booking
      summary: Detail booking
      operationId: booking_get_bookings
      security:
        - BearerAuth: []
      responses:
        "200": *a1
        "201": *a1
        "400": *a2
        "401": *a2
        "403": *a2
        "404": *a2
        "429":
          description: Rate limited — check Retry-After and X-RateLimit-* headers
          content: *a3
    patch:
      tags:
        - booking
      summary: Approve/reject (owner)
      operationId: booking_update_bookings
      security:
        - BearerAuth: []
      responses:
        "200": *a1
        "201": *a1
        "400": *a2
        "401": *a2
        "403": *a2
        "404": *a2
        "429":
          description: Rate limited — check Retry-After and X-RateLimit-* headers
          content: *a3
  /bookings/{id}/pay:
    post:
      tags:
        - booking
      summary: Inisiasi pembayaran Midtrans
      operationId: payment_initiate
      security:
        - BearerAuth: []
      responses:
        "200": *a1
        "201": *a1
        "400": *a2
        "401": *a2
        "403": *a2
        "404": *a2
        "429":
          description: Rate limited — check Retry-After and X-RateLimit-* headers
          content: *a3
  /platform/payment-options:
    get:
      tags:
        - payment
      summary: Opsi saluran pembayaran untuk booking
      operationId: payment_get_platform_payment-options
      security:
        - BearerAuth: []
      responses:
        "200": *a1
        "201": *a1
        "400": *a2
        "401": *a2
        "403": *a2
        "404": *a2
        "429":
          description: Rate limited — check Retry-After and X-RateLimit-* headers
          content: *a3
  /bookings/{id}/pay/offline/report:
    post:
      tags:
        - booking
      summary: Laporkan bukti transfer offline
      operationId: booking_create_bookings_by_id_pay_offline_report
      security:
        - BearerAuth: []
      responses:
        "200": *a1
        "201": *a1
        "400": *a2
        "401": *a2
        "403": *a2
        "404": *a2
        "429":
          description: Rate limited — check Retry-After and X-RateLimit-* headers
          content: *a3
  /bookings/{id}/pay/offline/confirm:
    post:
      tags:
        - booking
      summary: Konfirmasi/tolak bukti transfer offline (pemilik)
      operationId: booking_create_bookings_by_id_pay_offline_confirm
      security:
        - BearerAuth: []
      responses:
        "200": *a1
        "201": *a1
        "400": *a2
        "401": *a2
        "403": *a2
        "404": *a2
        "429":
          description: Rate limited — check Retry-After and X-RateLimit-* headers
          content: *a3
  /bookings/{id}/messages:
    get:
      tags:
        - booking
      summary: Chat log
      operationId: booking_get_bookings_by_id_messages
      security:
        - BearerAuth: []
      responses:
        "200": *a1
        "201": *a1
        "400": *a2
        "401": *a2
        "403": *a2
        "404": *a2
        "429":
          description: Rate limited — check Retry-After and X-RateLimit-* headers
          content: *a3
    post:
      tags:
        - booking
      summary: Kirim pesan
      operationId: booking_create_bookings_by_id_messages
      security:
        - BearerAuth: []
      responses:
        "200": *a1
        "201": *a1
        "400": *a2
        "401": *a2
        "403": *a2
        "404": *a2
        "429":
          description: Rate limited — check Retry-After and X-RateLimit-* headers
          content: *a3
  /bookings/{id}/messages/stream:
    get:
      tags:
        - booking
      summary: SSE chat stream
      operationId: booking_get_bookings_by_id_messages_stream
      security:
        - BearerAuth: []
      responses:
        "200": *a1
        "201": *a1
        "400": *a2
        "401": *a2
        "403": *a2
        "404": *a2
        "429":
          description: Rate limited — check Retry-After and X-RateLimit-* headers
          content: *a3
  /chat/conversations:
    get:
      tags:
        - chat
      summary: Daftar percakapan booking aktif
      operationId: chat_get_chat_conversations
      security:
        - BearerAuth: []
      responses:
        "200": *a1
        "201": *a1
        "400": *a2
        "401": *a2
        "403": *a2
        "404": *a2
        "429":
          description: Rate limited — check Retry-After and X-RateLimit-* headers
          content: *a3
  /chat/stream:
    get:
      tags:
        - chat
      summary: SSE user-level chat
      operationId: chat_get_chat_stream
      security:
        - BearerAuth: []
      responses:
        "200": *a1
        "201": *a1
        "400": *a2
        "401": *a2
        "403": *a2
        "404": *a2
        "429":
          description: Rate limited — check Retry-After and X-RateLimit-* headers
          content: *a3
  /owner/chat-metrics:
    get:
      tags:
        - owner
      summary: Metrik kecepatan respons chat
      operationId: owner_get_owner_chat-metrics
      security:
        - BearerAuth: []
      responses:
        "200": *a1
        "201": *a1
        "400": *a2
        "401": *a2
        "403": *a2
        "404": *a2
        "429":
          description: Rate limited — check Retry-After and X-RateLimit-* headers
          content: *a3
  /bookings/{id}/extensions:
    get:
      tags:
        - booking
      summary: List perpanjangan
      operationId: booking_get_bookings_by_id_extensions
      security:
        - BearerAuth: []
      responses:
        "200": *a1
        "201": *a1
        "400": *a2
        "401": *a2
        "403": *a2
        "404": *a2
        "429":
          description: Rate limited — check Retry-After and X-RateLimit-* headers
          content: *a3
    post:
      tags:
        - booking
      summary: Ajukan perpanjangan (penyewa)
      operationId: booking_create_bookings_by_id_extensions
      security:
        - BearerAuth: []
      responses:
        "200": *a1
        "201": *a1
        "400": *a2
        "401": *a2
        "403": *a2
        "404": *a2
        "429":
          description: Rate limited — check Retry-After and X-RateLimit-* headers
          content: *a3
    patch:
      tags:
        - booking
      summary: Setujui/tolak perpanjangan (pemilik)
      operationId: booking_update_bookings_by_id_extensions
      security:
        - BearerAuth: []
      responses:
        "200": *a1
        "201": *a1
        "400": *a2
        "401": *a2
        "403": *a2
        "404": *a2
        "429":
          description: Rate limited — check Retry-After and X-RateLimit-* headers
          content: *a3
  /bookings/{id}/incidents:
    get:
      tags:
        - booking
      summary: List insiden
      operationId: booking_get_bookings_by_id_incidents
      security:
        - BearerAuth: []
      responses:
        "200": *a1
        "201": *a1
        "400": *a2
        "401": *a2
        "403": *a2
        "404": *a2
        "429":
          description: Rate limited — check Retry-After and X-RateLimit-* headers
          content: *a3
    post:
      tags:
        - booking
      summary: Laporkan insiden
      operationId: booking_create_bookings_by_id_incidents
      security:
        - BearerAuth: []
      responses:
        "200": *a1
        "201": *a1
        "400": *a2
        "401": *a2
        "403": *a2
        "404": *a2
        "429":
          description: Rate limited — check Retry-After and X-RateLimit-* headers
          content: *a3
    patch:
      tags:
        - booking
      summary: Acknowledge/resolve insiden
      operationId: booking_update_bookings_by_id_incidents
      security:
        - BearerAuth: []
      responses:
        "200": *a1
        "201": *a1
        "400": *a2
        "401": *a2
        "403": *a2
        "404": *a2
        "429":
          description: Rate limited — check Retry-After and X-RateLimit-* headers
          content: *a3
  /bookings/{id}/dispute:
    get:
      tags:
        - booking
      summary: Detail sengketa
      operationId: booking_get_bookings_by_id_dispute
      security:
        - BearerAuth: []
      responses:
        "200": *a1
        "201": *a1
        "400": *a2
        "401": *a2
        "403": *a2
        "404": *a2
        "429":
          description: Rate limited — check Retry-After and X-RateLimit-* headers
          content: *a3
    post:
      tags:
        - booking
      summary: Buka sengketa
      operationId: booking_create_bookings_by_id_dispute
      security:
        - BearerAuth: []
      responses:
        "200": *a1
        "201": *a1
        "400": *a2
        "401": *a2
        "403": *a2
        "404": *a2
        "429":
          description: Rate limited — check Retry-After and X-RateLimit-* headers
          content: *a3
  /bookings/{id}/collateral:
    patch:
      tags:
        - booking
      summary: Ganti jaminan fisik (penyewa/pemilik, sebelum sewa dimulai)
      operationId: booking_update_bookings_by_id_collateral
      security:
        - BearerAuth: []
      responses:
        "200": *a1
        "201": *a1
        "400": *a2
        "401": *a2
        "403": *a2
        "404": *a2
        "429":
          description: Rate limited — check Retry-After and X-RateLimit-* headers
          content: *a3
  /reviews:
    get:
      tags:
        - reviews
      summary: Ulasan per booking (+ canReview)
      operationId: reviews_list
      security:
        - BearerAuth: []
      responses:
        "200": *a1
        "201": *a1
        "400": *a2
        "401": *a2
        "403": *a2
        "404": *a2
        "429":
          description: Rate limited — check Retry-After and X-RateLimit-* headers
          content: *a3
    post:
      tags:
        - reviews
      summary: Kirim ulasan booking
      operationId: reviews_create
      security:
        - BearerAuth: []
      responses:
        "200": *a1
        "201": *a1
        "400": *a2
        "401": *a2
        "403": *a2
        "404": *a2
        "429":
          description: Rate limited — check Retry-After and X-RateLimit-* headers
          content: *a3
  /notifications:
    get:
      tags:
        - notifications
      summary: Notifikasi in-app
      operationId: notifications_list
      security:
        - BearerAuth: []
      responses:
        "200": *a1
        "201": *a1
        "400": *a2
        "401": *a2
        "403": *a2
        "404": *a2
        "429":
          description: Rate limited — check Retry-After and X-RateLimit-* headers
          content: *a3
    patch:
      tags:
        - notifications
      summary: Tandai dibaca
      operationId: notifications_update
      security:
        - BearerAuth: []
      responses:
        "200": *a1
        "201": *a1
        "400": *a2
        "401": *a2
        "403": *a2
        "404": *a2
        "429":
          description: Rate limited — check Retry-After and X-RateLimit-* headers
          content: *a3
  /notifications/stream:
    get:
      tags:
        - notifications
      summary: SSE notifikasi real-time
      operationId: notifications_get_notifications_stream
      security:
        - BearerAuth: []
      responses:
        "200": *a1
        "201": *a1
        "400": *a2
        "401": *a2
        "403": *a2
        "404": *a2
        "429":
          description: Rate limited — check Retry-After and X-RateLimit-* headers
          content: *a3
  /push/subscribe:
    post:
      tags:
        - notifications
      summary: Subscribe push (web/mobile)
      operationId: notifications_create_push_subscribe
      security:
        - BearerAuth: []
      responses:
        "200": *a1
        "201": *a1
        "400": *a2
        "401": *a2
        "403": *a2
        "404": *a2
        "429":
          description: Rate limited — check Retry-After and X-RateLimit-* headers
          content: *a3
    get:
      tags:
        - notifications
      summary: Status push + VAPID public key
      operationId: notifications_get_push_subscribe
      security:
        - BearerAuth: []
      responses:
        "200": *a1
        "201": *a1
        "400": *a2
        "401": *a2
        "403": *a2
        "404": *a2
        "429":
          description: Rate limited — check Retry-After and X-RateLimit-* headers
          content: *a3
    delete:
      tags:
        - notifications
      summary: Hapus push subscription
      operationId: notifications_delete_push_subscribe
      security:
        - BearerAuth: []
      responses:
        "200": *a1
        "201": *a1
        "400": *a2
        "401": *a2
        "403": *a2
        "404": *a2
        "429":
          description: Rate limited — check Retry-After and X-RateLimit-* headers
          content: *a3
  /owner/calendar:
    get:
      tags:
        - owner
      summary: Kalender pemilik (blackout + booking aktif)
      operationId: owner_get_owner_calendar
      security:
        - BearerAuth: []
      responses:
        "200": *a1
        "201": *a1
        "400": *a2
        "401": *a2
        "403": *a2
        "404": *a2
        "429":
          description: Rate limited — check Retry-After and X-RateLimit-* headers
          content: *a3
  /owner/requests:
    get:
      tags:
        - owner
      summary: Inbox permintaan sewa menunggu persetujuan
      operationId: owner_get_owner_requests
      security:
        - BearerAuth: []
      responses:
        "200": *a1
        "201": *a1
        "400": *a2
        "401": *a2
        "403": *a2
        "404": *a2
        "429":
          description: Rate limited — check Retry-After and X-RateLimit-* headers
          content: *a3
  /owner/requests/{id}/documents:
    get:
      tags:
        - owner
      summary: Dokumen penyewa untuk review pemilik
      operationId: owner_get_owner_requests_by_id_documents
      security:
        - BearerAuth: []
      responses:
        "200": *a1
        "201": *a1
        "400": *a2
        "401": *a2
        "403": *a2
        "404": *a2
        "429":
          description: Rate limited — check Retry-After and X-RateLimit-* headers
          content: *a3
    patch:
      tags:
        - owner
      summary: Setujui/tolak dokumen penyewa (pemilik)
      operationId: owner_update_owner_requests_by_id_documents
      security:
        - BearerAuth: []
      responses:
        "200": *a1
        "201": *a1
        "400": *a2
        "401": *a2
        "403": *a2
        "404": *a2
        "429":
          description: Rate limited — check Retry-After and X-RateLimit-* headers
          content: *a3
  /owner/requests/{id}/snapshot:
    get:
      tags:
        - owner
      summary: Snapshot profil penyewa untuk review pemilik
      operationId: owner_get_owner_requests_by_id_snapshot
      security:
        - BearerAuth: []
      responses:
        "200": *a1
        "201": *a1
        "400": *a2
        "401": *a2
        "403": *a2
        "404": *a2
        "429":
          description: Rate limited — check Retry-After and X-RateLimit-* headers
          content: *a3
  /owner/bookings:
    get:
      tags:
        - owner
      summary: Daftar booking aset pemilik (filter=all|pending|active|completed|cancelled)
      operationId: owner_get_owner_bookings
      security:
        - BearerAuth: []
      responses:
        "200": *a1
        "201": *a1
        "400": *a2
        "401": *a2
        "403": *a2
        "404": *a2
        "429":
          description: Rate limited — check Retry-After and X-RateLimit-* headers
          content: *a3
  /owner/analytics:
    get:
      tags:
        - owner
      summary: Dashboard analytics vendor (query days=7|30|90)
      operationId: owner_get_owner_analytics
      security:
        - BearerAuth: []
      responses:
        "200": *a1
        "201": *a1
        "400": *a2
        "401": *a2
        "403": *a2
        "404": *a2
        "429":
          description: Rate limited — check Retry-After and X-RateLimit-* headers
          content: *a3
  /owner/payouts:
    get:
      tags:
        - owner
      summary: Riwayat payout vendor (status, amount, booking)
      operationId: owner_get_owner_payouts
      security:
        - BearerAuth: []
      responses:
        "200": *a1
        "201": *a1
        "400": *a2
        "401": *a2
        "403": *a2
        "404": *a2
        "429":
          description: Rate limited — check Retry-After and X-RateLimit-* headers
          content: *a3
  /owner/finance/summary:
    get:
      tags:
        - owner
      summary: Ringkasan Finance Hub (pendapatan, OpEx, margin)
      operationId: owner_get_owner_finance_summary
      security:
        - BearerAuth: []
      responses:
        "200": *a1
        "201": *a1
        "400": *a2
        "401": *a2
        "403": *a2
        "404": *a2
        "429":
          description: Rate limited — check Retry-After and X-RateLimit-* headers
          content: *a3
  /owner/finance/entries:
    get:
      tags:
        - owner
      summary: Daftar entri keuangan vendor
      operationId: owner_get_owner_finance_entries
      security:
        - BearerAuth: []
      responses:
        "200": *a1
        "201": *a1
        "400": *a2
        "401": *a2
        "403": *a2
        "404": *a2
        "429":
          description: Rate limited — check Retry-After and X-RateLimit-* headers
          content: *a3
    post:
      tags:
        - owner
      summary: Buat entri keuangan manual
      operationId: owner_create_owner_finance_entries
      security:
        - BearerAuth: []
      responses:
        "200": *a1
        "201": *a1
        "400": *a2
        "401": *a2
        "403": *a2
        "404": *a2
        "429":
          description: Rate limited — check Retry-After and X-RateLimit-* headers
          content: *a3
  /owner/finance/entries/{id}:
    get:
      tags:
        - owner
      summary: Detail entri keuangan
      operationId: owner_get_owner_finance_entries
      security:
        - BearerAuth: []
      responses:
        "200": *a1
        "201": *a1
        "400": *a2
        "401": *a2
        "403": *a2
        "404": *a2
        "429":
          description: Rate limited — check Retry-After and X-RateLimit-* headers
          content: *a3
    patch:
      tags:
        - owner
      summary: Update entri keuangan
      operationId: owner_update_owner_finance_entries
      security:
        - BearerAuth: []
      responses:
        "200": *a1
        "201": *a1
        "400": *a2
        "401": *a2
        "403": *a2
        "404": *a2
        "429":
          description: Rate limited — check Retry-After and X-RateLimit-* headers
          content: *a3
    delete:
      tags:
        - owner
      summary: Void entri keuangan
      operationId: owner_delete_owner_finance_entries
      security:
        - BearerAuth: []
      responses:
        "200": *a1
        "201": *a1
        "400": *a2
        "401": *a2
        "403": *a2
        "404": *a2
        "429":
          description: Rate limited — check Retry-After and X-RateLimit-* headers
          content: *a3
  /owner/finance/categories:
    get:
      tags:
        - owner
      summary: Kategori entri keuangan
      operationId: owner_get_owner_finance_categories
      security:
        - BearerAuth: []
      responses:
        "200": *a1
        "201": *a1
        "400": *a2
        "401": *a2
        "403": *a2
        "404": *a2
        "429":
          description: Rate limited — check Retry-After and X-RateLimit-* headers
          content: *a3
  /owner/finance/opex/checklist:
    get:
      tags:
        - owner
      summary: Checklist OpEx bulanan
      operationId: owner_get_owner_finance_opex_checklist
      security:
        - BearerAuth: []
      responses:
        "200": *a1
        "201": *a1
        "400": *a2
        "401": *a2
        "403": *a2
        "404": *a2
        "429":
          description: Rate limited — check Retry-After and X-RateLimit-* headers
          content: *a3
  /owner/finance/opex/quick-add:
    post:
      tags:
        - owner
      summary: Quick-add OpEx dari checklist
      operationId: owner_create_owner_finance_opex_quick-add
      security:
        - BearerAuth: []
      responses:
        "200": *a1
        "201": *a1
        "400": *a2
        "401": *a2
        "403": *a2
        "404": *a2
        "429":
          description: Rate limited — check Retry-After and X-RateLimit-* headers
          content: *a3
  /owner/payout-bank:
    get:
      tags:
        - owner
      summary: Rekening penerima payout
      operationId: owner_get_owner_payout-bank
      security:
        - BearerAuth: []
      responses:
        "200": *a1
        "201": *a1
        "400": *a2
        "401": *a2
        "403": *a2
        "404": *a2
        "429":
          description: Rate limited — check Retry-After and X-RateLimit-* headers
          content: *a3
    patch:
      tags:
        - owner
      summary: Update rekening penerima payout
      operationId: owner_update_owner_payout-bank
      security:
        - BearerAuth: []
      responses:
        "200": *a1
        "201": *a1
        "400": *a2
        "401": *a2
        "403": *a2
        "404": *a2
        "429":
          description: Rate limited — check Retry-After and X-RateLimit-* headers
          content: *a3
  /owner/assets:
    get:
      tags:
        - owner
      summary: Daftar aset milik vendor
      operationId: owner_get_owner_assets
      security:
        - BearerAuth: []
      responses:
        "200": *a1
        "201": *a1
        "400": *a2
        "401": *a2
        "403": *a2
        "404": *a2
        "429":
          description: Rate limited — check Retry-After and X-RateLimit-* headers
          content: *a3
    post:
      tags:
        - owner
      summary: Buat aset baru
      operationId: owner_create_owner_assets
      security:
        - BearerAuth: []
      responses:
        "200": *a1
        "201": *a1
        "400": *a2
        "401": *a2
        "403": *a2
        "404": *a2
        "429":
          description: Rate limited — check Retry-After and X-RateLimit-* headers
          content: *a3
  /owner/assets/{id}:
    get:
      tags:
        - owner
      summary: Detail aset milik vendor
      operationId: owner_get_owner_assets
      security:
        - BearerAuth: []
      responses:
        "200": *a1
        "201": *a1
        "400": *a2
        "401": *a2
        "403": *a2
        "404": *a2
        "429":
          description: Rate limited — check Retry-After and X-RateLimit-* headers
          content: *a3
    patch:
      tags:
        - owner
      summary: Update aset (info/pricing/section)
      operationId: owner_update_owner_assets
      security:
        - BearerAuth: []
      responses:
        "200": *a1
        "201": *a1
        "400": *a2
        "401": *a2
        "403": *a2
        "404": *a2
        "429":
          description: Rate limited — check Retry-After and X-RateLimit-* headers
          content: *a3
  /owner/assets/{id}/blackouts:
    get:
      tags:
        - owner
      summary: Daftar blackout aset
      operationId: owner_get_owner_assets_by_id_blackouts
      security:
        - BearerAuth: []
      responses:
        "200": *a1
        "201": *a1
        "400": *a2
        "401": *a2
        "403": *a2
        "404": *a2
        "429":
          description: Rate limited — check Retry-After and X-RateLimit-* headers
          content: *a3
    post:
      tags:
        - owner
      summary: Tambah blackout
      operationId: owner_create_owner_assets_by_id_blackouts
      security:
        - BearerAuth: []
      responses:
        "200": *a1
        "201": *a1
        "400": *a2
        "401": *a2
        "403": *a2
        "404": *a2
        "429":
          description: Rate limited — check Retry-After and X-RateLimit-* headers
          content: *a3
    delete:
      tags:
        - owner
      summary: Hapus blackout (query blackoutId)
      operationId: owner_delete_owner_assets_by_id_blackouts
      security:
        - BearerAuth: []
      responses:
        "200": *a1
        "201": *a1
        "400": *a2
        "401": *a2
        "403": *a2
        "404": *a2
        "429":
          description: Rate limited — check Retry-After and X-RateLimit-* headers
          content: *a3
  /owner/storefront:
    get:
      tags:
        - owner
      summary: Profil storefront vendor
      operationId: owner_get_owner_storefront
      security:
        - BearerAuth: []
      responses:
        "200": *a1
        "201": *a1
        "400": *a2
        "401": *a2
        "403": *a2
        "404": *a2
        "429":
          description: Rate limited — check Retry-After and X-RateLimit-* headers
          content: *a3
    patch:
      tags:
        - owner
      summary: Update branding storefront
      operationId: owner_update_owner_storefront
      security:
        - BearerAuth: []
      responses:
        "200": *a1
        "201": *a1
        "400": *a2
        "401": *a2
        "403": *a2
        "404": *a2
        "429":
          description: Rate limited — check Retry-After and X-RateLimit-* headers
          content: *a3
  /owner/storefront-slug/check:
    get:
      tags:
        - owner
      summary: Cek ketersediaan username mini-site (query q)
      operationId: owner_get_owner_storefront-slug_check
      security:
        - BearerAuth: []
      responses:
        "200": *a1
        "201": *a1
        "400": *a2
        "401": *a2
        "403": *a2
        "404": *a2
        "429":
          description: Rate limited — check Retry-After and X-RateLimit-* headers
          content: *a3
  /owner/storefront-slug:
    patch:
      tags:
        - owner
      summary: Ubah username mini-site vendor
      operationId: owner_update_owner_storefront-slug
      security:
        - BearerAuth: []
      responses:
        "200": *a1
        "201": *a1
        "400": *a2
        "401": *a2
        "403": *a2
        "404": *a2
        "429":
          description: Rate limited — check Retry-After and X-RateLimit-* headers
          content: *a3
  /owner/duration-rules:
    get:
      tags:
        - owner
      summary: Vendor-wide default duration rules
      operationId: owner_get_owner_duration-rules
      security:
        - BearerAuth: []
      responses:
        "200": *a1
        "201": *a1
        "400": *a2
        "401": *a2
        "403": *a2
        "404": *a2
        "429":
          description: Rate limited — check Retry-After and X-RateLimit-* headers
          content: *a3
    patch:
      tags:
        - owner
      summary: Upsert vendor-wide default duration rules
      operationId: owner_update_owner_duration-rules
      security:
        - BearerAuth: []
      responses:
        "200": *a1
        "201": *a1
        "400": *a2
        "401": *a2
        "403": *a2
        "404": *a2
        "429":
          description: Rate limited — check Retry-After and X-RateLimit-* headers
          content: *a3
  /owner/feedback:
    get:
      tags:
        - owner
      summary: Riwayat saran pemilik
      operationId: owner_get_owner_feedback
      security:
        - BearerAuth: []
      responses:
        "200": *a1
        "201": *a1
        "400": *a2
        "401": *a2
        "403": *a2
        "404": *a2
        "429":
          description: Rate limited — check Retry-After and X-RateLimit-* headers
          content: *a3
    post:
      tags:
        - owner
      summary: Kirim saran pemilik
      operationId: owner_create_owner_feedback
      security:
        - BearerAuth: []
      responses:
        "200": *a1
        "201": *a1
        "400": *a2
        "401": *a2
        "403": *a2
        "404": *a2
        "429":
          description: Rate limited — check Retry-After and X-RateLimit-* headers
          content: *a3
  /bookings/{id}/condition:
    post:
      tags:
        - booking
      summary: Submit laporan kondisi check-in/out
      operationId: booking_create_bookings_by_id_condition
      security:
        - BearerAuth: []
      responses:
        "200": *a1
        "201": *a1
        "400": *a2
        "401": *a2
        "403": *a2
        "404": *a2
        "429":
          description: Rate limited — check Retry-After and X-RateLimit-* headers
          content: *a3
    patch:
      tags:
        - booking
      summary: Konfirmasi check-in oleh penyewa
      operationId: booking_update_bookings_by_id_condition
      security:
        - BearerAuth: []
      responses:
        "200": *a1
        "201": *a1
        "400": *a2
        "401": *a2
        "403": *a2
        "404": *a2
        "429":
          description: Rate limited — check Retry-After and X-RateLimit-* headers
          content: *a3
  /bookings/{id}/pay/status:
    get:
      tags:
        - booking
      summary: Sinkron status pembayaran Midtrans
      operationId: booking_get_bookings_by_id_pay_status
      security:
        - BearerAuth: []
      responses:
        "200": *a1
        "201": *a1
        "400": *a2
        "401": *a2
        "403": *a2
        "404": *a2
        "429":
          description: Rate limited — check Retry-After and X-RateLimit-* headers
          content: *a3
  /bookings/{id}/payments/{paymentId}/invoice:
    get:
      tags:
        - booking
      summary: Invoice HTML pembayaran (printable)
      operationId: booking_get_bookings_by_id_payments_by_id_invoice
      security:
        - BearerAuth: []
      responses:
        "200": *a1
        "201": *a1
        "400": *a2
        "401": *a2
        "403": *a2
        "404": *a2
        "429":
          description: Rate limited — check Retry-After and X-RateLimit-* headers
          content: *a3
  /bookings/{id}/counter-offer:
    get:
      tags:
        - booking
      summary: Detail counter-offer booking
      operationId: booking_get_bookings_by_id_counter-offer
      security:
        - BearerAuth: []
      responses:
        "200": *a1
        "201": *a1
        "400": *a2
        "401": *a2
        "403": *a2
        "404": *a2
        "429":
          description: Rate limited — check Retry-After and X-RateLimit-* headers
          content: *a3
    post:
      tags:
        - booking
      summary: Kirim counter-offer (pemilik)
      operationId: booking_create_bookings_by_id_counter-offer
      security:
        - BearerAuth: []
      responses:
        "200": *a1
        "201": *a1
        "400": *a2
        "401": *a2
        "403": *a2
        "404": *a2
        "429":
          description: Rate limited — check Retry-After and X-RateLimit-* headers
          content: *a3
    patch:
      tags:
        - booking
      summary: Terima/tolak counter-offer (penyewa)
      operationId: booking_update_bookings_by_id_counter-offer
      security:
        - BearerAuth: []
      responses:
        "200": *a1
        "201": *a1
        "400": *a2
        "401": *a2
        "403": *a2
        "404": *a2
        "429":
          description: Rate limited — check Retry-After and X-RateLimit-* headers
          content: *a3
  /bookings/{id}/promote:
    post:
      tags:
        - booking
      summary: Promosikan booking PENDING_VERIFICATION ke inbox pemilik
      operationId: booking_promote
      security:
        - BearerAuth: []
      responses:
        "200": *a1
        "201": *a1
        "400": *a2
        "401": *a2
        "403": *a2
        "404": *a2
        "429":
          description: Rate limited — check Retry-After and X-RateLimit-* headers
          content: *a3
  /bookings/{id}/cancel:
    post:
      tags:
        - booking
      summary: Batalkan booking oleh penyewa
      operationId: booking_create_bookings_by_id_cancel
      security:
        - BearerAuth: []
      responses:
        "200": *a1
        "201": *a1
        "400": *a2
        "401": *a2
        "403": *a2
        "404": *a2
        "429":
          description: Rate limited — check Retry-After and X-RateLimit-* headers
          content: *a3
  /bookings/active:
    get:
      tags:
        - booking
      summary: Booking aktif penyewa untuk banner beranda
      operationId: booking_get_bookings_active
      security:
        - BearerAuth: []
      responses:
        "200": *a1
        "201": *a1
        "400": *a2
        "401": *a2
        "403": *a2
        "404": *a2
        "429":
          description: Rate limited — check Retry-After and X-RateLimit-* headers
          content: *a3
  /bookings/{id}/readiness:
    get:
      tags:
        - booking
      summary: Status booking + nextActions untuk AI agent
      operationId: booking_get_bookings_by_id_readiness
      security:
        - BearerAuth: []
      responses:
        "200": *a1
        "201": *a1
        "400": *a2
        "401": *a2
        "403": *a2
        "404": *a2
        "429":
          description: Rate limited — check Retry-After and X-RateLimit-* headers
          content: *a3
  /auth/api-keys:
    get:
      tags:
        - auth
      summary: Daftar API key scoped user
      operationId: auth_get_auth_api-keys
      security:
        - BearerAuth: []
      responses:
        "200": *a1
        "201": *a1
        "400": *a2
        "401": *a2
        "403": *a2
        "404": *a2
        "429":
          description: Rate limited — check Retry-After and X-RateLimit-* headers
          content: *a3
    post:
      tags:
        - auth
      summary: Buat API key scoped (read:catalog, write:booking, …)
      operationId: auth_create_auth_api-keys
      security:
        - BearerAuth: []
      responses:
        "200": *a1
        "201": *a1
        "400": *a2
        "401": *a2
        "403": *a2
        "404": *a2
        "429":
          description: Rate limited — check Retry-After and X-RateLimit-* headers
          content: *a3
    delete:
      tags:
        - auth
      summary: Revoke API key (query keyId)
      operationId: auth_delete_auth_api-keys
      security:
        - BearerAuth: []
      responses:
        "200": *a1
        "201": *a1
        "400": *a2
        "401": *a2
        "403": *a2
        "404": *a2
        "429":
          description: Rate limited — check Retry-After and X-RateLimit-* headers
          content: *a3
  /auth/api-keys/{id}/rotate:
    post:
      tags:
        - auth
      summary: Rotate API key — revoke lama, issue secret baru
      operationId: auth_create_auth_api-keys_by_id_rotate
      security:
        - BearerAuth: []
      responses:
        "200": *a1
        "201": *a1
        "400": *a2
        "401": *a2
        "403": *a2
        "404": *a2
        "429":
          description: Rate limited — check Retry-After and X-RateLimit-* headers
          content: *a3
  /webhooks/agent:
    get:
      tags:
        - payment
      summary: List webhook agent terdaftar
      operationId: payment_get_webhooks_agent
      security:
        - BearerAuth: []
      responses:
        "200": *a1
        "201": *a1
        "400": *a2
        "401": *a2
        "403": *a2
        "404": *a2
        "429":
          description: Rate limited — check Retry-After and X-RateLimit-* headers
          content: *a3
    post:
      tags:
        - payment
      summary: Daftar webhook agent partner (HMAC)
      operationId: payment_create_webhooks_agent
      security:
        - BearerAuth: []
      responses:
        "200": *a1
        "201": *a1
        "400": *a2
        "401": *a2
        "403": *a2
        "404": *a2
        "429":
          description: Rate limited — check Retry-After and X-RateLimit-* headers
          content: *a3
  /admin/agent-usage:
    get:
      tags:
        - admin
      summary: Metrik penggunaan API agent (admin)
      operationId: admin_get_admin_agent-usage
      security:
        - BearerAuth: []
      responses:
        "200": *a1
        "201": *a1
        "400": *a2
        "401": *a2
        "403": *a2
        "404": *a2
        "429":
          description: Rate limited — check Retry-After and X-RateLimit-* headers
          content: *a3
  /admin/payments:
    get:
      tags:
        - admin
      summary: Daftar transaksi pembayaran (tab=fraud|reconciliation untuk antrean fraud & export CSV)
      operationId: admin_get_admin_payments
      security:
        - BearerAuth: []
      responses:
        "200": *a1
        "201": *a1
        "400": *a2
        "401": *a2
        "403": *a2
        "404": *a2
        "429":
          description: Rate limited — check Retry-After and X-RateLimit-* headers
          content: *a3
    patch:
      tags:
        - admin
      summary: Approve/reject fraud challenge, grant credit, manual refund
      operationId: admin_update_admin_payments
      security:
        - BearerAuth: []
      responses:
        "200": *a1
        "201": *a1
        "400": *a2
        "401": *a2
        "403": *a2
        "404": *a2
        "429":
          description: Rate limited — check Retry-After and X-RateLimit-* headers
          content: *a3
  /admin/payments/payouts/{id}:
    patch:
      tags:
        - admin
      summary: Retry payout gagal atau mark complete (action=complete|retry)
      operationId: admin_update_admin_payments_payouts
      security:
        - BearerAuth: []
      responses:
        "200": *a1
        "201": *a1
        "400": *a2
        "401": *a2
        "403": *a2
        "404": *a2
        "429":
          description: Rate limited — check Retry-After and X-RateLimit-* headers
          content: *a3
  /cron/payment-expire:
    post:
      tags:
        - payment
      summary: Cron expire pembayaran PENDING > 24h (Bearer CRON_SECRET)
      operationId: payment_create_cron_payment-expire
      security:
        - BearerAuth: []
      responses:
        "200": *a1
        "201": *a1
        "400": *a2
        "401": *a2
        "403": *a2
        "404": *a2
        "429":
          description: Rate limited — check Retry-After and X-RateLimit-* headers
          content: *a3
  /cron/deposit-release:
    post:
      tags:
        - internal
      summary: Cron pelepasan deposit setelah grace period (Bearer CRON_SECRET)
      operationId: internal_create_cron_deposit-release
      security:
        - BearerAuth: []
      responses:
        "200": *a1
        "201": *a1
        "400": *a2
        "401": *a2
        "403": *a2
        "404": *a2
        "429":
          description: Rate limited — check Retry-After and X-RateLimit-* headers
          content: *a3
  /cron/silent-acceptance:
    post:
      tags:
        - internal
      summary: Cron silent acceptance 48h olahraga/hobi (Bearer CRON_SECRET)
      operationId: internal_create_cron_silent-acceptance
      security:
        - BearerAuth: []
      responses:
        "200": *a1
        "201": *a1
        "400": *a2
        "401": *a2
        "403": *a2
        "404": *a2
        "429":
          description: Rate limited — check Retry-After and X-RateLimit-* headers
          content: *a3
components:
  securitySchemes:
    BearerAuth:
      type: http
      scheme: bearer
      bearerFormat: JWT
      description: "JWT from POST /auth/login, or scoped API key (sp_test_… / sp_live_…) via Authorization: Bearer or
        X-Api-Key header"
  schemas:
    ApiSuccess:
      type: object
      required:
        - success
        - data
      properties:
        success:
          type: boolean
          enum:
            - true
        data: {}
    ApiError:
      type: object
      required:
        - success
        - error
      properties:
        success:
          type: boolean
          enum:
            - false
        error:
          type: string
    PaginationMeta:
      type: object
      properties:
        page:
          type: integer
        limit:
          type: integer
        total:
          type: integer
        totalPages:
          type: integer
    LoginRequest:
      $ref: ../schemas/LoginRequest.json
    LoginResponse:
      $ref: ../schemas/LoginResponse.json
    CreateBookingRequest:
      $ref: ../schemas/CreateBookingRequest.json
    PricingQuoteRequest:
      $ref: ../schemas/PricingQuoteRequest.json
    BookingReadiness:
      $ref: ../schemas/BookingReadiness.json
    AssetAvailability:
      $ref: ../schemas/AssetAvailability.json
    CatalogFeedItem:
      $ref: ../schemas/CatalogFeedItem.json
