components:
  schemas:
    github_com_trakrf_platform_backend_internal_models_apikey.APIKeyCreateResponse:
      properties:
        created_at:
          format: date-time
          type: string
        expires_at:
          format: date-time
          type: string
        id:
          type: integer
        jti:
          type: string
        key:
          type: string
        name:
          type: string
        scopes:
          items:
            type: string
          type: array
      type: object
    github_com_trakrf_platform_backend_internal_models_apikey.APIKeyListItem:
      properties:
        created_at:
          format: date-time
          type: string
        created_by:
          type: integer
        created_by_key_id:
          type: integer
        expires_at:
          format: date-time
          type: string
        id:
          type: integer
        jti:
          type: string
        last_used_at:
          format: date-time
          type: string
        name:
          type: string
        scopes:
          items:
            type: string
          type: array
      type: object
    github_com_trakrf_platform_backend_internal_models_apikey.CreateAPIKeyRequest:
      properties:
        expires_at:
          format: date-time
          type: string
        name:
          maxLength: 255
          minLength: 1
          type: string
        scopes:
          items:
            type: string
          minItems: 1
          type: array
      required:
        - name
        - scopes
      type: object
    github_com_trakrf_platform_backend_internal_models_asset.CreateAssetWithIdentifiersRequest:
      properties:
        current_location:
          example: WHS-01
          maxLength: 255
          minLength: 1
          type: string
        description:
          maxLength: 1024
          type: string
        identifier:
          maxLength: 255
          type: string
        identifiers:
          items:
            $ref: >-
              #/components/schemas/github_com_trakrf_platform_backend_internal_models_shared.TagIdentifierRequest
          type: array
        is_active:
          example: true
          type: boolean
        metadata:
          additionalProperties: true
          type: object
        name:
          maxLength: 255
          minLength: 1
          type: string
        type:
          enum:
            - asset
            - person
            - inventory
          example: asset
          type: string
        valid_from:
          example: '2025-01-01T00:00:00Z'
          format: date-time
          type: string
        valid_to:
          example: '2026-01-01T00:00:00Z'
          format: date-time
          type: string
      required:
        - name
      type: object
    github_com_trakrf_platform_backend_internal_models_asset.PublicAssetView:
      properties:
        created_at:
          format: date-time
          type: string
        current_location:
          type: string
        description:
          type: string
        identifier:
          type: string
        identifiers:
          items:
            $ref: >-
              #/components/schemas/github_com_trakrf_platform_backend_internal_models_shared.TagIdentifier
          type: array
        is_active:
          type: boolean
        metadata:
          additionalProperties: true
          type: object
        name:
          type: string
        surrogate_id:
          type: integer
        type:
          type: string
        updated_at:
          format: date-time
          type: string
        valid_from:
          format: date-time
          type: string
        valid_to:
          format: date-time
          type: string
      type: object
    github_com_trakrf_platform_backend_internal_models_asset.UpdateAssetRequest:
      properties:
        current_location:
          example: WHS-01
          maxLength: 255
          minLength: 1
          type: string
        description:
          maxLength: 1024
          type: string
        identifier:
          maxLength: 255
          minLength: 1
          type: string
        is_active:
          type: boolean
        metadata:
          additionalProperties: true
          type: object
        name:
          maxLength: 255
          minLength: 1
          type: string
        type:
          enum:
            - asset
            - person
            - inventory
          type: string
        valid_from:
          example: '2025-01-01T00:00:00Z'
          format: date-time
          type: string
        valid_to:
          example: '2026-01-01T00:00:00Z'
          format: date-time
          type: string
      type: object
    github_com_trakrf_platform_backend_internal_models_errors.ErrorResponse:
      properties:
        error:
          properties:
            detail:
              type: string
            fields:
              items:
                $ref: >-
                  #/components/schemas/github_com_trakrf_platform_backend_internal_models_errors.FieldError
              type: array
            instance:
              type: string
            request_id:
              type: string
            status:
              type: integer
            title:
              type: string
            type:
              enum:
                - validation_error
                - bad_request
                - unauthorized
                - forbidden
                - not_found
                - conflict
                - rate_limited
                - internal_error
              example: validation_error
              type: string
              x-extensible-enum: true
          type: object
      type: object
    github_com_trakrf_platform_backend_internal_models_errors.FieldError:
      properties:
        code:
          type: string
        field:
          type: string
        message:
          type: string
        params:
          additionalProperties: {}
          type: object
      type: object
    github_com_trakrf_platform_backend_internal_models_location.CreateLocationWithIdentifiersRequest:
      properties:
        description:
          example: Main warehouse location
          maxLength: 1024
          type: string
        identifier:
          example: wh1
          maxLength: 255
          minLength: 1
          type: string
        identifiers:
          items:
            $ref: >-
              #/components/schemas/github_com_trakrf_platform_backend_internal_models_shared.TagIdentifierRequest
          type: array
        is_active:
          example: true
          type: boolean
        name:
          example: Warehouse 1
          maxLength: 255
          minLength: 1
          type: string
        parent_identifier:
          example: wh1
          maxLength: 255
          minLength: 1
          type: string
        valid_from:
          example: '2025-12-14T00:00:00Z'
          format: date-time
          type: string
        valid_to:
          example: '2026-12-14T00:00:00Z'
          format: date-time
          type: string
      required:
        - identifier
        - name
      type: object
    github_com_trakrf_platform_backend_internal_models_location.PublicLocationView:
      properties:
        created_at:
          format: date-time
          type: string
        depth:
          type: integer
        description:
          type: string
        identifier:
          type: string
        identifiers:
          items:
            $ref: >-
              #/components/schemas/github_com_trakrf_platform_backend_internal_models_shared.TagIdentifier
          type: array
        is_active:
          type: boolean
        name:
          type: string
        parent:
          type: string
        path:
          type: string
        surrogate_id:
          type: integer
        updated_at:
          format: date-time
          type: string
        valid_from:
          format: date-time
          type: string
        valid_to:
          format: date-time
          type: string
      type: object
    github_com_trakrf_platform_backend_internal_models_location.UpdateLocationRequest:
      properties:
        description:
          example: Updated description
          maxLength: 1024
          type: string
        identifier:
          example: wh1
          maxLength: 255
          minLength: 1
          type: string
        is_active:
          example: true
          type: boolean
        name:
          example: Warehouse 1
          maxLength: 255
          minLength: 1
          type: string
        parent_identifier:
          example: wh1
          maxLength: 255
          minLength: 1
          type: string
        valid_from:
          example: '2025-12-14T00:00:00Z'
          format: date-time
          type: string
        valid_to:
          example: '2026-12-14T00:00:00Z'
          format: date-time
          type: string
      type: object
    github_com_trakrf_platform_backend_internal_models_report.PublicAssetHistoryItem:
      properties:
        duration_seconds:
          type: integer
        location:
          type: string
        timestamp:
          format: date-time
          type: string
      type: object
    github_com_trakrf_platform_backend_internal_models_report.PublicCurrentLocationItem:
      properties:
        asset:
          type: string
        last_seen:
          format: date-time
          type: string
        location:
          type: string
      type: object
    github_com_trakrf_platform_backend_internal_models_shared.TagIdentifier:
      properties:
        id:
          type: integer
        is_active:
          type: boolean
        type:
          enum:
            - rfid
            - ble
            - barcode
          example: rfid
          type: string
          x-extensible-enum: true
        value:
          maxLength: 255
          minLength: 1
          type: string
      required:
        - type
        - value
      type: object
    github_com_trakrf_platform_backend_internal_models_shared.TagIdentifierRequest:
      properties:
        type:
          enum:
            - rfid
            - ble
            - barcode
          example: rfid
          type: string
          x-extensible-enum: true
        value:
          maxLength: 255
          minLength: 1
          type: string
      required:
        - value
      type: object
    github_com_trakrf_platform_backend_internal_storage.SaveInventoryResult:
      properties:
        count:
          type: integer
        location_id:
          type: integer
        location_name:
          type: string
        timestamp:
          format: date-time
          type: string
      type: object
    internal_handlers_assets.CreateAssetResponse:
      properties:
        data:
          $ref: >-
            #/components/schemas/github_com_trakrf_platform_backend_internal_models_asset.PublicAssetView
      type: object
    internal_handlers_assets.GetAssetResponse:
      properties:
        data:
          $ref: >-
            #/components/schemas/github_com_trakrf_platform_backend_internal_models_asset.PublicAssetView
      type: object
    internal_handlers_assets.ListAssetsResponse:
      properties:
        data:
          items:
            $ref: >-
              #/components/schemas/github_com_trakrf_platform_backend_internal_models_asset.PublicAssetView
          type: array
        limit:
          example: 50
          type: integer
        offset:
          example: 0
          type: integer
        total_count:
          example: 100
          type: integer
      type: object
    internal_handlers_assets.UpdateAssetResponse:
      properties:
        data:
          $ref: >-
            #/components/schemas/github_com_trakrf_platform_backend_internal_models_asset.PublicAssetView
      type: object
    internal_handlers_inventory.SaveRequest:
      properties:
        asset_identifiers:
          example:
            - ASSET-0001
          items:
            type: string
          minItems: 1
          type: array
        location_identifier:
          example: WH-01
          maxLength: 255
          minLength: 1
          type: string
      type: object
    internal_handlers_inventory.SaveResponse:
      properties:
        data:
          $ref: >-
            #/components/schemas/github_com_trakrf_platform_backend_internal_storage.SaveInventoryResult
      type: object
    internal_handlers_locations.CreateLocationResponse:
      properties:
        data:
          $ref: >-
            #/components/schemas/github_com_trakrf_platform_backend_internal_models_location.PublicLocationView
      type: object
    internal_handlers_locations.GetLocationResponse:
      properties:
        data:
          $ref: >-
            #/components/schemas/github_com_trakrf_platform_backend_internal_models_location.PublicLocationView
      type: object
    internal_handlers_locations.ListAncestorsResponse:
      properties:
        data:
          items:
            $ref: >-
              #/components/schemas/github_com_trakrf_platform_backend_internal_models_location.PublicLocationView
          type: array
        limit:
          example: 50
          type: integer
        offset:
          example: 0
          type: integer
        total_count:
          example: 100
          type: integer
      type: object
    internal_handlers_locations.ListChildrenResponse:
      properties:
        data:
          items:
            $ref: >-
              #/components/schemas/github_com_trakrf_platform_backend_internal_models_location.PublicLocationView
          type: array
        limit:
          example: 50
          type: integer
        offset:
          example: 0
          type: integer
        total_count:
          example: 100
          type: integer
      type: object
    internal_handlers_locations.ListDescendantsResponse:
      properties:
        data:
          items:
            $ref: >-
              #/components/schemas/github_com_trakrf_platform_backend_internal_models_location.PublicLocationView
          type: array
        limit:
          example: 50
          type: integer
        offset:
          example: 0
          type: integer
        total_count:
          example: 100
          type: integer
      type: object
    internal_handlers_locations.ListLocationsResponse:
      properties:
        data:
          items:
            $ref: >-
              #/components/schemas/github_com_trakrf_platform_backend_internal_models_location.PublicLocationView
          type: array
        limit:
          example: 50
          type: integer
        offset:
          example: 0
          type: integer
        total_count:
          example: 100
          type: integer
      type: object
    internal_handlers_locations.UpdateLocationResponse:
      properties:
        data:
          $ref: >-
            #/components/schemas/github_com_trakrf_platform_backend_internal_models_location.PublicLocationView
      type: object
    internal_handlers_orgs.CreateAPIKeyResponse:
      properties:
        data:
          $ref: >-
            #/components/schemas/github_com_trakrf_platform_backend_internal_models_apikey.APIKeyCreateResponse
      type: object
    internal_handlers_orgs.GetOrgMeResponse:
      properties:
        data:
          $ref: '#/components/schemas/internal_handlers_orgs.OrgMeView'
      type: object
    internal_handlers_orgs.ListAPIKeysResponse:
      properties:
        data:
          items:
            $ref: >-
              #/components/schemas/github_com_trakrf_platform_backend_internal_models_apikey.APIKeyListItem
          type: array
        limit:
          example: 50
          type: integer
        offset:
          example: 0
          type: integer
        total_count:
          example: 100
          type: integer
      type: object
    internal_handlers_orgs.OrgMeView:
      properties:
        id:
          example: 42
          type: integer
        name:
          example: Acme Logistics
          type: string
      type: object
    internal_handlers_reports.AssetHistoryResponse:
      properties:
        data:
          items:
            $ref: >-
              #/components/schemas/github_com_trakrf_platform_backend_internal_models_report.PublicAssetHistoryItem
          type: array
        limit:
          example: 50
          type: integer
        offset:
          example: 0
          type: integer
        total_count:
          example: 100
          type: integer
      type: object
    internal_handlers_reports.ListCurrentLocationsResponse:
      properties:
        data:
          items:
            $ref: >-
              #/components/schemas/github_com_trakrf_platform_backend_internal_models_report.PublicCurrentLocationItem
          type: array
        limit:
          example: 50
          type: integer
        offset:
          example: 0
          type: integer
        total_count:
          example: 100
          type: integer
      type: object
  securitySchemes:
    APIKey:
      description: >-
        TrakRF API key (JWT). Format: "Bearer <jwt>". Mint keys from the API
        Keys section of your TrakRF account.
      in: header
      name: Authorization
      type: apiKey
    BearerAuth:
      bearerFormat: JWT
      description: Session JWT for internal endpoints (platform frontend uses this).
      scheme: bearer
      type: http
info:
  contact:
    email: support@trakrf.id
    name: TrakRF Support
  description: >-
    TrakRF public REST API. See docs.trakrf.id/api for the customer-facing
    reference.
  license:
    name: Business Source License 1.1
    url: https://github.com/trakrf/platform/blob/main/LICENSE
  title: TrakRF API
  version: v1
openapi: 3.0.3
paths:
  /api/v1/assets:
    get:
      description: >-
        Paginated assets list with natural-key filters, sort, and substring
        search
      operationId: assets.list
      parameters:
        - description: max 200
          in: query
          name: limit
          schema:
            default: 50
            type: integer
        - description: min 0
          in: query
          name: offset
          schema:
            default: 0
            type: integer
        - description: filter by location natural key (may repeat)
          in: query
          name: location
          schema:
            type: string
        - description: filter by active flag
          in: query
          name: is_active
          schema:
            type: boolean
        - description: filter by type
          in: query
          name: type
          schema:
            type: string
        - description: >-
            substring search (case-insensitive) on name, identifier,
            description, and active identifier values
          in: query
          name: q
          schema:
            type: string
        - description: comma-separated; prefix '-' for DESC
          in: query
          name: sort
          schema:
            type: string
      responses:
        '200':
          content:
            application/json:
              schema:
                $ref: >-
                  #/components/schemas/internal_handlers_assets.ListAssetsResponse
          description: OK
          headers:
            X-RateLimit-Limit:
              description: Steady-state requests/min for this API key
              schema:
                type: integer
            X-RateLimit-Remaining:
              description: >-
                Requests remaining before throttling; bounded by
                X-RateLimit-Limit
              schema:
                type: integer
            X-RateLimit-Reset:
              description: >-
                Unix timestamp (seconds) when X-RateLimit-Remaining will next
                equal X-RateLimit-Limit
              schema:
                type: integer
        '400':
          content:
            application/json:
              schema:
                $ref: >-
                  #/components/schemas/github_com_trakrf_platform_backend_internal_models_errors.ErrorResponse
          description: Bad Request
        '401':
          content:
            application/json:
              schema:
                $ref: >-
                  #/components/schemas/github_com_trakrf_platform_backend_internal_models_errors.ErrorResponse
          description: Unauthorized
        '403':
          content:
            application/json:
              schema:
                $ref: >-
                  #/components/schemas/github_com_trakrf_platform_backend_internal_models_errors.ErrorResponse
          description: Forbidden
        '429':
          content:
            application/json:
              schema:
                $ref: >-
                  #/components/schemas/github_com_trakrf_platform_backend_internal_models_errors.ErrorResponse
          description: rate_limited
          headers:
            Retry-After:
              description: Seconds to wait before retrying
              schema:
                type: integer
        '500':
          content:
            application/json:
              schema:
                $ref: >-
                  #/components/schemas/github_com_trakrf_platform_backend_internal_models_errors.ErrorResponse
          description: Internal Server Error
      security:
        - APIKey:
            - assets:read
      summary: List assets
      tags:
        - assets
    post:
      description: >-
        Create a new asset record, optionally with one or more tag identifiers
        (RFID, BLE, barcode).

        Returns the created asset with its assigned identifiers. The Location
        response header contains the canonical URL.
      operationId: assets.create
      requestBody:
        content:
          application/json:
            schema:
              $ref: >-
                #/components/schemas/github_com_trakrf_platform_backend_internal_models_asset.CreateAssetWithIdentifiersRequest
        description: Asset to create with optional identifiers
        required: true
        x-originalParamName: request
      responses:
        '201':
          content:
            application/json:
              schema:
                $ref: >-
                  #/components/schemas/internal_handlers_assets.CreateAssetResponse
          description: Created
        '400':
          content:
            application/json:
              schema:
                $ref: >-
                  #/components/schemas/github_com_trakrf_platform_backend_internal_models_errors.ErrorResponse
          description: bad_request
        '401':
          content:
            application/json:
              schema:
                $ref: >-
                  #/components/schemas/github_com_trakrf_platform_backend_internal_models_errors.ErrorResponse
          description: unauthorized
        '403':
          content:
            application/json:
              schema:
                $ref: >-
                  #/components/schemas/github_com_trakrf_platform_backend_internal_models_errors.ErrorResponse
          description: forbidden
        '409':
          content:
            application/json:
              schema:
                $ref: >-
                  #/components/schemas/github_com_trakrf_platform_backend_internal_models_errors.ErrorResponse
          description: conflict
        '429':
          content:
            application/json:
              schema:
                $ref: >-
                  #/components/schemas/github_com_trakrf_platform_backend_internal_models_errors.ErrorResponse
          description: rate_limited
        '500':
          content:
            application/json:
              schema:
                $ref: >-
                  #/components/schemas/github_com_trakrf_platform_backend_internal_models_errors.ErrorResponse
          description: internal_error
      security:
        - APIKey:
            - assets:write
      summary: Create an asset
      tags:
        - assets
  /api/v1/assets/{identifier}:
    delete:
      description: >-
        Delete an asset by its natural identifier. The asset is removed from all
        subsequent queries and its identifier becomes immediately available for
        reuse. Returns 204 on success, 404 if the asset does not exist or has
        already been deleted.
      operationId: assets.delete
      parameters:
        - description: Asset identifier
          in: path
          name: identifier
          required: true
          schema:
            type: string
      responses:
        '204':
          description: deleted
        '401':
          content:
            application/json:
              schema:
                $ref: >-
                  #/components/schemas/github_com_trakrf_platform_backend_internal_models_errors.ErrorResponse
          description: unauthorized
        '403':
          content:
            application/json:
              schema:
                $ref: >-
                  #/components/schemas/github_com_trakrf_platform_backend_internal_models_errors.ErrorResponse
          description: forbidden
        '404':
          content:
            application/json:
              schema:
                $ref: >-
                  #/components/schemas/github_com_trakrf_platform_backend_internal_models_errors.ErrorResponse
          description: not_found
        '429':
          content:
            application/json:
              schema:
                $ref: >-
                  #/components/schemas/github_com_trakrf_platform_backend_internal_models_errors.ErrorResponse
          description: rate_limited
        '500':
          content:
            application/json:
              schema:
                $ref: >-
                  #/components/schemas/github_com_trakrf_platform_backend_internal_models_errors.ErrorResponse
          description: internal_error
      security:
        - APIKey:
            - assets:write
      summary: Delete an asset
      tags:
        - assets
    get:
      description: >-
        Retrieve an asset by its natural identifier. Returns 404 if the asset
        does not exist.
      operationId: assets.get
      parameters:
        - description: Asset identifier (natural key)
          in: path
          name: identifier
          required: true
          schema:
            type: string
      responses:
        '200':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/internal_handlers_assets.GetAssetResponse'
          description: OK
          headers:
            X-RateLimit-Limit:
              description: Steady-state requests/min for this API key
              schema:
                type: integer
            X-RateLimit-Remaining:
              description: >-
                Requests remaining before throttling; bounded by
                X-RateLimit-Limit
              schema:
                type: integer
            X-RateLimit-Reset:
              description: >-
                Unix timestamp (seconds) when X-RateLimit-Remaining will next
                equal X-RateLimit-Limit
              schema:
                type: integer
        '400':
          content:
            application/json:
              schema:
                $ref: >-
                  #/components/schemas/github_com_trakrf_platform_backend_internal_models_errors.ErrorResponse
          description: Bad Request
        '401':
          content:
            application/json:
              schema:
                $ref: >-
                  #/components/schemas/github_com_trakrf_platform_backend_internal_models_errors.ErrorResponse
          description: Unauthorized
        '403':
          content:
            application/json:
              schema:
                $ref: >-
                  #/components/schemas/github_com_trakrf_platform_backend_internal_models_errors.ErrorResponse
          description: Forbidden
        '404':
          content:
            application/json:
              schema:
                $ref: >-
                  #/components/schemas/github_com_trakrf_platform_backend_internal_models_errors.ErrorResponse
          description: Not Found
        '429':
          content:
            application/json:
              schema:
                $ref: >-
                  #/components/schemas/github_com_trakrf_platform_backend_internal_models_errors.ErrorResponse
          description: rate_limited
          headers:
            Retry-After:
              description: Seconds to wait before retrying
              schema:
                type: integer
      security:
        - APIKey:
            - assets:read
      summary: Get asset by natural identifier
      tags:
        - assets
    put:
      description: >-
        Update mutable fields on an existing asset. Only fields included in the
        request body are changed.
      operationId: assets.update
      parameters:
        - description: Asset identifier
          in: path
          name: identifier
          required: true
          schema:
            type: string
      requestBody:
        content:
          application/json:
            schema:
              $ref: >-
                #/components/schemas/github_com_trakrf_platform_backend_internal_models_asset.UpdateAssetRequest
        description: Fields to update
        required: true
        x-originalParamName: request
      responses:
        '200':
          content:
            application/json:
              schema:
                $ref: >-
                  #/components/schemas/internal_handlers_assets.UpdateAssetResponse
          description: OK
        '400':
          content:
            application/json:
              schema:
                $ref: >-
                  #/components/schemas/github_com_trakrf_platform_backend_internal_models_errors.ErrorResponse
          description: bad_request
        '401':
          content:
            application/json:
              schema:
                $ref: >-
                  #/components/schemas/github_com_trakrf_platform_backend_internal_models_errors.ErrorResponse
          description: unauthorized
        '403':
          content:
            application/json:
              schema:
                $ref: >-
                  #/components/schemas/github_com_trakrf_platform_backend_internal_models_errors.ErrorResponse
          description: forbidden
        '404':
          content:
            application/json:
              schema:
                $ref: >-
                  #/components/schemas/github_com_trakrf_platform_backend_internal_models_errors.ErrorResponse
          description: not_found
        '409':
          content:
            application/json:
              schema:
                $ref: >-
                  #/components/schemas/github_com_trakrf_platform_backend_internal_models_errors.ErrorResponse
          description: conflict
        '429':
          content:
            application/json:
              schema:
                $ref: >-
                  #/components/schemas/github_com_trakrf_platform_backend_internal_models_errors.ErrorResponse
          description: rate_limited
        '500':
          content:
            application/json:
              schema:
                $ref: >-
                  #/components/schemas/github_com_trakrf_platform_backend_internal_models_errors.ErrorResponse
          description: internal_error
      security:
        - APIKey:
            - assets:write
      summary: Update an asset
      tags:
        - assets
  /api/v1/assets/{identifier}/history:
    get:
      description: Location history for an asset identified by its natural key.
      operationId: assets.history
      parameters:
        - description: Asset identifier (natural key)
          in: path
          name: identifier
          required: true
          schema:
            type: string
        - description: max 200
          in: query
          name: limit
          schema:
            default: 50
            type: integer
        - description: min 0
          in: query
          name: offset
          schema:
            default: 0
            type: integer
        - description: RFC 3339 start timestamp
          in: query
          name: from
          schema:
            type: string
        - description: RFC 3339 end timestamp
          in: query
          name: to
          schema:
            type: string
      responses:
        '200':
          content:
            application/json:
              schema:
                $ref: >-
                  #/components/schemas/internal_handlers_reports.AssetHistoryResponse
          description: OK
          headers:
            X-RateLimit-Limit:
              description: Steady-state requests/min for this API key
              schema:
                type: integer
            X-RateLimit-Remaining:
              description: >-
                Requests remaining before throttling; bounded by
                X-RateLimit-Limit
              schema:
                type: integer
            X-RateLimit-Reset:
              description: >-
                Unix timestamp (seconds) when X-RateLimit-Remaining will next
                equal X-RateLimit-Limit
              schema:
                type: integer
        '400':
          content:
            application/json:
              schema:
                $ref: >-
                  #/components/schemas/github_com_trakrf_platform_backend_internal_models_errors.ErrorResponse
          description: Bad Request
        '401':
          content:
            application/json:
              schema:
                $ref: >-
                  #/components/schemas/github_com_trakrf_platform_backend_internal_models_errors.ErrorResponse
          description: Unauthorized
        '403':
          content:
            application/json:
              schema:
                $ref: >-
                  #/components/schemas/github_com_trakrf_platform_backend_internal_models_errors.ErrorResponse
          description: Forbidden
        '404':
          content:
            application/json:
              schema:
                $ref: >-
                  #/components/schemas/github_com_trakrf_platform_backend_internal_models_errors.ErrorResponse
          description: Not Found
        '429':
          content:
            application/json:
              schema:
                $ref: >-
                  #/components/schemas/github_com_trakrf_platform_backend_internal_models_errors.ErrorResponse
          description: rate_limited
          headers:
            Retry-After:
              description: Seconds to wait before retrying
              schema:
                type: integer
        '500':
          content:
            application/json:
              schema:
                $ref: >-
                  #/components/schemas/github_com_trakrf_platform_backend_internal_models_errors.ErrorResponse
          description: Internal Server Error
      security:
        - APIKey:
            - scans:read
      summary: Asset movement history
      tags:
        - reports
  /api/v1/assets/{identifier}/identifiers:
    post:
      description: >-
        Attach a tag identifier (RFID EPC, BLE beacon ID, barcode, etc.) to an
        existing asset.

        The identifier must be unique within the organization.
      operationId: assets.identifiers.add
      parameters:
        - description: Asset identifier
          in: path
          name: identifier
          required: true
          schema:
            type: string
      requestBody:
        content:
          application/json:
            schema:
              $ref: >-
                #/components/schemas/github_com_trakrf_platform_backend_internal_models_shared.TagIdentifierRequest
        description: Tag identifier to attach
        required: true
        x-originalParamName: request
      responses:
        '201':
          content:
            application/json:
              schema:
                additionalProperties: true
                type: object
          description: 'data: shared.TagIdentifier'
        '400':
          content:
            application/json:
              schema:
                $ref: >-
                  #/components/schemas/github_com_trakrf_platform_backend_internal_models_errors.ErrorResponse
          description: bad_request
        '401':
          content:
            application/json:
              schema:
                $ref: >-
                  #/components/schemas/github_com_trakrf_platform_backend_internal_models_errors.ErrorResponse
          description: unauthorized
        '403':
          content:
            application/json:
              schema:
                $ref: >-
                  #/components/schemas/github_com_trakrf_platform_backend_internal_models_errors.ErrorResponse
          description: forbidden
        '404':
          content:
            application/json:
              schema:
                $ref: >-
                  #/components/schemas/github_com_trakrf_platform_backend_internal_models_errors.ErrorResponse
          description: not_found
        '429':
          content:
            application/json:
              schema:
                $ref: >-
                  #/components/schemas/github_com_trakrf_platform_backend_internal_models_errors.ErrorResponse
          description: rate_limited
        '500':
          content:
            application/json:
              schema:
                $ref: >-
                  #/components/schemas/github_com_trakrf_platform_backend_internal_models_errors.ErrorResponse
          description: internal_error
      security:
        - APIKey:
            - assets:write
      summary: Add an identifier to an asset
      tags:
        - assets
  /api/v1/assets/{identifier}/identifiers/{identifierId}:
    delete:
      description: Detach a tag identifier from an asset by its identifier record ID.
      operationId: assets.identifiers.remove
      parameters:
        - description: Asset identifier
          in: path
          name: identifier
          required: true
          schema:
            type: string
        - description: Identifier ID
          in: path
          name: identifierId
          required: true
          schema:
            type: integer
      responses:
        '204':
          description: deleted
        '400':
          content:
            application/json:
              schema:
                $ref: >-
                  #/components/schemas/github_com_trakrf_platform_backend_internal_models_errors.ErrorResponse
          description: bad_request
        '401':
          content:
            application/json:
              schema:
                $ref: >-
                  #/components/schemas/github_com_trakrf_platform_backend_internal_models_errors.ErrorResponse
          description: unauthorized
        '403':
          content:
            application/json:
              schema:
                $ref: >-
                  #/components/schemas/github_com_trakrf_platform_backend_internal_models_errors.ErrorResponse
          description: forbidden
        '404':
          content:
            application/json:
              schema:
                $ref: >-
                  #/components/schemas/github_com_trakrf_platform_backend_internal_models_errors.ErrorResponse
          description: not_found
        '429':
          content:
            application/json:
              schema:
                $ref: >-
                  #/components/schemas/github_com_trakrf_platform_backend_internal_models_errors.ErrorResponse
          description: rate_limited
        '500':
          content:
            application/json:
              schema:
                $ref: >-
                  #/components/schemas/github_com_trakrf_platform_backend_internal_models_errors.ErrorResponse
          description: internal_error
      security:
        - APIKey:
            - assets:write
      summary: Remove an identifier from an asset
      tags:
        - assets
  /api/v1/inventory/save:
    post:
      description: Persist scanned RFID assets to the asset_scans hypertable
      operationId: inventory.save
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/internal_handlers_inventory.SaveRequest'
        description: Save request with location and asset IDs
        required: true
        x-originalParamName: request
      responses:
        '201':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/internal_handlers_inventory.SaveResponse'
          description: Created
        '400':
          content:
            application/json:
              schema:
                $ref: >-
                  #/components/schemas/github_com_trakrf_platform_backend_internal_models_errors.ErrorResponse
          description: Invalid request
        '401':
          content:
            application/json:
              schema:
                $ref: >-
                  #/components/schemas/github_com_trakrf_platform_backend_internal_models_errors.ErrorResponse
          description: Unauthorized
        '403':
          content:
            application/json:
              schema:
                $ref: >-
                  #/components/schemas/github_com_trakrf_platform_backend_internal_models_errors.ErrorResponse
          description: Location or assets not owned by org
        '429':
          content:
            application/json:
              schema:
                $ref: >-
                  #/components/schemas/github_com_trakrf_platform_backend_internal_models_errors.ErrorResponse
          description: rate_limited
          headers:
            Retry-After:
              description: Seconds to wait before retrying
              schema:
                type: integer
        '500':
          content:
            application/json:
              schema:
                $ref: >-
                  #/components/schemas/github_com_trakrf_platform_backend_internal_models_errors.ErrorResponse
          description: Internal server error
      security:
        - APIKey:
            - scans:write
      summary: Save inventory scans
      tags:
        - inventory
  /api/v1/locations:
    get:
      operationId: locations.list
      parameters:
        - description: max 200
          in: query
          name: limit
          schema:
            default: 50
            type: integer
        - description: min 0
          in: query
          name: offset
          schema:
            default: 0
            type: integer
        - description: filter by parent identifier (may repeat)
          in: query
          name: parent
          schema:
            type: string
        - description: filter by active flag
          in: query
          name: is_active
          schema:
            type: boolean
        - description: >-
            substring search (case-insensitive) on name, identifier,
            description, and active identifier values
          in: query
          name: q
          schema:
            type: string
        - description: comma-separated, prefix '-' for DESC
          in: query
          name: sort
          schema:
            type: string
      responses:
        '200':
          content:
            application/json:
              schema:
                $ref: >-
                  #/components/schemas/internal_handlers_locations.ListLocationsResponse
          description: OK
          headers:
            X-RateLimit-Limit:
              description: Steady-state requests/min for this API key
              schema:
                type: integer
            X-RateLimit-Remaining:
              description: >-
                Requests remaining before throttling; bounded by
                X-RateLimit-Limit
              schema:
                type: integer
            X-RateLimit-Reset:
              description: >-
                Unix timestamp (seconds) when X-RateLimit-Remaining will next
                equal X-RateLimit-Limit
              schema:
                type: integer
        '400':
          content:
            application/json:
              schema:
                $ref: >-
                  #/components/schemas/github_com_trakrf_platform_backend_internal_models_errors.ErrorResponse
          description: bad_request
        '401':
          content:
            application/json:
              schema:
                $ref: >-
                  #/components/schemas/github_com_trakrf_platform_backend_internal_models_errors.ErrorResponse
          description: unauthorized
        '403':
          content:
            application/json:
              schema:
                $ref: >-
                  #/components/schemas/github_com_trakrf_platform_backend_internal_models_errors.ErrorResponse
          description: forbidden
        '429':
          content:
            application/json:
              schema:
                $ref: >-
                  #/components/schemas/github_com_trakrf_platform_backend_internal_models_errors.ErrorResponse
          description: rate_limited
          headers:
            Retry-After:
              description: Seconds to wait before retrying
              schema:
                type: integer
      security:
        - APIKey:
            - locations:read
      summary: List locations
      tags:
        - locations
    post:
      description: >-
        Create a new location in the hierarchy, optionally with one or more tag
        identifiers.

        Set ParentLocationID to nest the location under an existing parent. The
        Location response header contains the canonical URL.
      operationId: locations.create
      requestBody:
        content:
          application/json:
            schema:
              $ref: >-
                #/components/schemas/github_com_trakrf_platform_backend_internal_models_location.CreateLocationWithIdentifiersRequest
        description: Location to create with optional identifiers
        required: true
        x-originalParamName: request
      responses:
        '201':
          content:
            application/json:
              schema:
                $ref: >-
                  #/components/schemas/internal_handlers_locations.CreateLocationResponse
          description: Created
        '400':
          content:
            application/json:
              schema:
                $ref: >-
                  #/components/schemas/github_com_trakrf_platform_backend_internal_models_errors.ErrorResponse
          description: bad_request
        '401':
          content:
            application/json:
              schema:
                $ref: >-
                  #/components/schemas/github_com_trakrf_platform_backend_internal_models_errors.ErrorResponse
          description: unauthorized
        '403':
          content:
            application/json:
              schema:
                $ref: >-
                  #/components/schemas/github_com_trakrf_platform_backend_internal_models_errors.ErrorResponse
          description: forbidden
        '409':
          content:
            application/json:
              schema:
                $ref: >-
                  #/components/schemas/github_com_trakrf_platform_backend_internal_models_errors.ErrorResponse
          description: conflict
        '429':
          content:
            application/json:
              schema:
                $ref: >-
                  #/components/schemas/github_com_trakrf_platform_backend_internal_models_errors.ErrorResponse
          description: rate_limited
        '500':
          content:
            application/json:
              schema:
                $ref: >-
                  #/components/schemas/github_com_trakrf_platform_backend_internal_models_errors.ErrorResponse
          description: internal_error
      security:
        - APIKey:
            - locations:write
      summary: Create a location
      tags:
        - locations
  /api/v1/locations/{identifier}:
    delete:
      description: >-
        Delete a location by its natural identifier. The location is removed
        from all subsequent queries and its identifier becomes immediately
        available for reuse. Returns 204 on success, 404 if the location does
        not exist or has already been deleted.
      operationId: locations.delete
      parameters:
        - description: Location identifier
          in: path
          name: identifier
          required: true
          schema:
            type: string
      responses:
        '204':
          description: deleted
        '400':
          content:
            application/json:
              schema:
                $ref: >-
                  #/components/schemas/github_com_trakrf_platform_backend_internal_models_errors.ErrorResponse
          description: bad_request
        '401':
          content:
            application/json:
              schema:
                $ref: >-
                  #/components/schemas/github_com_trakrf_platform_backend_internal_models_errors.ErrorResponse
          description: unauthorized
        '403':
          content:
            application/json:
              schema:
                $ref: >-
                  #/components/schemas/github_com_trakrf_platform_backend_internal_models_errors.ErrorResponse
          description: forbidden
        '404':
          content:
            application/json:
              schema:
                $ref: >-
                  #/components/schemas/github_com_trakrf_platform_backend_internal_models_errors.ErrorResponse
          description: not_found
        '429':
          content:
            application/json:
              schema:
                $ref: >-
                  #/components/schemas/github_com_trakrf_platform_backend_internal_models_errors.ErrorResponse
          description: rate_limited
        '500':
          content:
            application/json:
              schema:
                $ref: >-
                  #/components/schemas/github_com_trakrf_platform_backend_internal_models_errors.ErrorResponse
          description: internal_error
      security:
        - APIKey:
            - locations:write
      summary: Delete location
      tags:
        - locations
    get:
      description: >-
        Retrieve a location by its natural identifier. Returns 404 if the
        location does not exist.
      operationId: locations.get
      parameters:
        - description: Location identifier (natural key)
          in: path
          name: identifier
          required: true
          schema:
            type: string
      responses:
        '200':
          content:
            application/json:
              schema:
                $ref: >-
                  #/components/schemas/internal_handlers_locations.GetLocationResponse
          description: OK
          headers:
            X-RateLimit-Limit:
              description: Steady-state requests/min for this API key
              schema:
                type: integer
            X-RateLimit-Remaining:
              description: >-
                Requests remaining before throttling; bounded by
                X-RateLimit-Limit
              schema:
                type: integer
            X-RateLimit-Reset:
              description: >-
                Unix timestamp (seconds) when X-RateLimit-Remaining will next
                equal X-RateLimit-Limit
              schema:
                type: integer
        '400':
          content:
            application/json:
              schema:
                $ref: >-
                  #/components/schemas/github_com_trakrf_platform_backend_internal_models_errors.ErrorResponse
          description: Bad Request
        '401':
          content:
            application/json:
              schema:
                $ref: >-
                  #/components/schemas/github_com_trakrf_platform_backend_internal_models_errors.ErrorResponse
          description: Unauthorized
        '403':
          content:
            application/json:
              schema:
                $ref: >-
                  #/components/schemas/github_com_trakrf_platform_backend_internal_models_errors.ErrorResponse
          description: Forbidden
        '404':
          content:
            application/json:
              schema:
                $ref: >-
                  #/components/schemas/github_com_trakrf_platform_backend_internal_models_errors.ErrorResponse
          description: Not Found
        '429':
          content:
            application/json:
              schema:
                $ref: >-
                  #/components/schemas/github_com_trakrf_platform_backend_internal_models_errors.ErrorResponse
          description: rate_limited
          headers:
            Retry-After:
              description: Seconds to wait before retrying
              schema:
                type: integer
      security:
        - APIKey:
            - locations:read
      summary: Get location by natural identifier
      tags:
        - locations
    put:
      description: >-
        Update mutable fields on an existing location. Only fields included in
        the request body are changed.
      operationId: locations.update
      parameters:
        - description: Location identifier
          in: path
          name: identifier
          required: true
          schema:
            type: string
      requestBody:
        content:
          application/json:
            schema:
              $ref: >-
                #/components/schemas/github_com_trakrf_platform_backend_internal_models_location.UpdateLocationRequest
        description: Fields to update
        required: true
        x-originalParamName: request
      responses:
        '200':
          content:
            application/json:
              schema:
                $ref: >-
                  #/components/schemas/internal_handlers_locations.UpdateLocationResponse
          description: OK
        '400':
          content:
            application/json:
              schema:
                $ref: >-
                  #/components/schemas/github_com_trakrf_platform_backend_internal_models_errors.ErrorResponse
          description: bad_request
        '401':
          content:
            application/json:
              schema:
                $ref: >-
                  #/components/schemas/github_com_trakrf_platform_backend_internal_models_errors.ErrorResponse
          description: unauthorized
        '403':
          content:
            application/json:
              schema:
                $ref: >-
                  #/components/schemas/github_com_trakrf_platform_backend_internal_models_errors.ErrorResponse
          description: forbidden
        '404':
          content:
            application/json:
              schema:
                $ref: >-
                  #/components/schemas/github_com_trakrf_platform_backend_internal_models_errors.ErrorResponse
          description: not_found
        '409':
          content:
            application/json:
              schema:
                $ref: >-
                  #/components/schemas/github_com_trakrf_platform_backend_internal_models_errors.ErrorResponse
          description: conflict
        '429':
          content:
            application/json:
              schema:
                $ref: >-
                  #/components/schemas/github_com_trakrf_platform_backend_internal_models_errors.ErrorResponse
          description: rate_limited
        '500':
          content:
            application/json:
              schema:
                $ref: >-
                  #/components/schemas/github_com_trakrf_platform_backend_internal_models_errors.ErrorResponse
          description: internal_error
      security:
        - APIKey:
            - locations:write
      summary: Update a location
      tags:
        - locations
  /api/v1/locations/{identifier}/ancestors:
    get:
      description: >-
        Return all ancestor locations from the root of the hierarchy down to the
        immediate parent of the specified location.
      operationId: locations.ancestors
      parameters:
        - description: Location identifier
          in: path
          name: identifier
          required: true
          schema:
            type: string
        - description: max 200
          in: query
          name: limit
          schema:
            default: 50
            type: integer
        - description: min 0
          in: query
          name: offset
          schema:
            default: 0
            type: integer
      responses:
        '200':
          content:
            application/json:
              schema:
                $ref: >-
                  #/components/schemas/internal_handlers_locations.ListAncestorsResponse
          description: OK
        '400':
          content:
            application/json:
              schema:
                $ref: >-
                  #/components/schemas/github_com_trakrf_platform_backend_internal_models_errors.ErrorResponse
          description: bad_request
        '401':
          content:
            application/json:
              schema:
                $ref: >-
                  #/components/schemas/github_com_trakrf_platform_backend_internal_models_errors.ErrorResponse
          description: unauthorized
        '403':
          content:
            application/json:
              schema:
                $ref: >-
                  #/components/schemas/github_com_trakrf_platform_backend_internal_models_errors.ErrorResponse
          description: forbidden
        '429':
          content:
            application/json:
              schema:
                $ref: >-
                  #/components/schemas/github_com_trakrf_platform_backend_internal_models_errors.ErrorResponse
          description: rate_limited
        '500':
          content:
            application/json:
              schema:
                $ref: >-
                  #/components/schemas/github_com_trakrf_platform_backend_internal_models_errors.ErrorResponse
          description: internal_error
      security:
        - APIKey:
            - locations:read
      summary: List location ancestors
      tags:
        - locations
  /api/v1/locations/{identifier}/children:
    get:
      description: >-
        Return the immediate child locations of the specified location (one
        level deep only).
      operationId: locations.children
      parameters:
        - description: Location identifier
          in: path
          name: identifier
          required: true
          schema:
            type: string
        - description: max 200
          in: query
          name: limit
          schema:
            default: 50
            type: integer
        - description: min 0
          in: query
          name: offset
          schema:
            default: 0
            type: integer
      responses:
        '200':
          content:
            application/json:
              schema:
                $ref: >-
                  #/components/schemas/internal_handlers_locations.ListChildrenResponse
          description: OK
        '400':
          content:
            application/json:
              schema:
                $ref: >-
                  #/components/schemas/github_com_trakrf_platform_backend_internal_models_errors.ErrorResponse
          description: bad_request
        '401':
          content:
            application/json:
              schema:
                $ref: >-
                  #/components/schemas/github_com_trakrf_platform_backend_internal_models_errors.ErrorResponse
          description: unauthorized
        '403':
          content:
            application/json:
              schema:
                $ref: >-
                  #/components/schemas/github_com_trakrf_platform_backend_internal_models_errors.ErrorResponse
          description: forbidden
        '429':
          content:
            application/json:
              schema:
                $ref: >-
                  #/components/schemas/github_com_trakrf_platform_backend_internal_models_errors.ErrorResponse
          description: rate_limited
        '500':
          content:
            application/json:
              schema:
                $ref: >-
                  #/components/schemas/github_com_trakrf_platform_backend_internal_models_errors.ErrorResponse
          description: internal_error
      security:
        - APIKey:
            - locations:read
      summary: List location children
      tags:
        - locations
  /api/v1/locations/{identifier}/descendants:
    get:
      description: >-
        Return all descendant locations (children, grandchildren, etc.) beneath
        the specified location in the hierarchy.
      operationId: locations.descendants
      parameters:
        - description: Location identifier
          in: path
          name: identifier
          required: true
          schema:
            type: string
        - description: max 200
          in: query
          name: limit
          schema:
            default: 50
            type: integer
        - description: min 0
          in: query
          name: offset
          schema:
            default: 0
            type: integer
      responses:
        '200':
          content:
            application/json:
              schema:
                $ref: >-
                  #/components/schemas/internal_handlers_locations.ListDescendantsResponse
          description: OK
        '400':
          content:
            application/json:
              schema:
                $ref: >-
                  #/components/schemas/github_com_trakrf_platform_backend_internal_models_errors.ErrorResponse
          description: bad_request
        '401':
          content:
            application/json:
              schema:
                $ref: >-
                  #/components/schemas/github_com_trakrf_platform_backend_internal_models_errors.ErrorResponse
          description: unauthorized
        '403':
          content:
            application/json:
              schema:
                $ref: >-
                  #/components/schemas/github_com_trakrf_platform_backend_internal_models_errors.ErrorResponse
          description: forbidden
        '429':
          content:
            application/json:
              schema:
                $ref: >-
                  #/components/schemas/github_com_trakrf_platform_backend_internal_models_errors.ErrorResponse
          description: rate_limited
        '500':
          content:
            application/json:
              schema:
                $ref: >-
                  #/components/schemas/github_com_trakrf_platform_backend_internal_models_errors.ErrorResponse
          description: internal_error
      security:
        - APIKey:
            - locations:read
      summary: List location descendants
      tags:
        - locations
  /api/v1/locations/{identifier}/identifiers:
    post:
      description: >-
        Attach a tag identifier (RFID EPC, BLE beacon ID, barcode, etc.) to an
        existing location.

        The identifier must be unique within the organization.
      operationId: locations.identifiers.add
      parameters:
        - description: Location identifier
          in: path
          name: identifier
          required: true
          schema:
            type: string
      requestBody:
        content:
          application/json:
            schema:
              $ref: >-
                #/components/schemas/github_com_trakrf_platform_backend_internal_models_shared.TagIdentifierRequest
        description: Tag identifier to attach
        required: true
        x-originalParamName: request
      responses:
        '201':
          content:
            application/json:
              schema:
                additionalProperties: true
                type: object
          description: 'data: shared.TagIdentifier'
        '400':
          content:
            application/json:
              schema:
                $ref: >-
                  #/components/schemas/github_com_trakrf_platform_backend_internal_models_errors.ErrorResponse
          description: bad_request
        '401':
          content:
            application/json:
              schema:
                $ref: >-
                  #/components/schemas/github_com_trakrf_platform_backend_internal_models_errors.ErrorResponse
          description: unauthorized
        '403':
          content:
            application/json:
              schema:
                $ref: >-
                  #/components/schemas/github_com_trakrf_platform_backend_internal_models_errors.ErrorResponse
          description: forbidden
        '404':
          content:
            application/json:
              schema:
                $ref: >-
                  #/components/schemas/github_com_trakrf_platform_backend_internal_models_errors.ErrorResponse
          description: not_found
        '429':
          content:
            application/json:
              schema:
                $ref: >-
                  #/components/schemas/github_com_trakrf_platform_backend_internal_models_errors.ErrorResponse
          description: rate_limited
        '500':
          content:
            application/json:
              schema:
                $ref: >-
                  #/components/schemas/github_com_trakrf_platform_backend_internal_models_errors.ErrorResponse
          description: internal_error
      security:
        - APIKey:
            - locations:write
      summary: Add an identifier to a location
      tags:
        - locations
  /api/v1/locations/{identifier}/identifiers/{identifierId}:
    delete:
      description: Detach a tag identifier from a location by its identifier record ID.
      operationId: locations.identifiers.remove
      parameters:
        - description: Location identifier
          in: path
          name: identifier
          required: true
          schema:
            type: string
        - description: Identifier ID
          in: path
          name: identifierId
          required: true
          schema:
            type: integer
      responses:
        '204':
          description: deleted
        '400':
          content:
            application/json:
              schema:
                $ref: >-
                  #/components/schemas/github_com_trakrf_platform_backend_internal_models_errors.ErrorResponse
          description: bad_request
        '401':
          content:
            application/json:
              schema:
                $ref: >-
                  #/components/schemas/github_com_trakrf_platform_backend_internal_models_errors.ErrorResponse
          description: unauthorized
        '403':
          content:
            application/json:
              schema:
                $ref: >-
                  #/components/schemas/github_com_trakrf_platform_backend_internal_models_errors.ErrorResponse
          description: forbidden
        '404':
          content:
            application/json:
              schema:
                $ref: >-
                  #/components/schemas/github_com_trakrf_platform_backend_internal_models_errors.ErrorResponse
          description: not_found
        '429':
          content:
            application/json:
              schema:
                $ref: >-
                  #/components/schemas/github_com_trakrf_platform_backend_internal_models_errors.ErrorResponse
          description: rate_limited
        '500':
          content:
            application/json:
              schema:
                $ref: >-
                  #/components/schemas/github_com_trakrf_platform_backend_internal_models_errors.ErrorResponse
          description: internal_error
      security:
        - APIKey:
            - locations:write
      summary: Remove an identifier from a location
      tags:
        - locations
  /api/v1/locations/current:
    get:
      description: >-
        Snapshot of each asset's most recent location, filterable by natural
        key.
      operationId: locations.current
      parameters:
        - description: max 200
          in: query
          name: limit
          schema:
            default: 50
            type: integer
        - description: min 0
          in: query
          name: offset
          schema:
            default: 0
            type: integer
        - description: filter by location identifier (may repeat)
          in: query
          name: location
          schema:
            type: string
        - description: >-
            substring search (case-insensitive) on asset name, identifier, and
            active identifier values
          in: query
          name: q
          schema:
            type: string
        - description: comma-separated sort fields; prefix '-' for DESC
          in: query
          name: sort
          schema:
            type: string
      responses:
        '200':
          content:
            application/json:
              schema:
                $ref: >-
                  #/components/schemas/internal_handlers_reports.ListCurrentLocationsResponse
          description: OK
          headers:
            X-RateLimit-Limit:
              description: Steady-state requests/min for this API key
              schema:
                type: integer
            X-RateLimit-Remaining:
              description: >-
                Requests remaining before throttling; bounded by
                X-RateLimit-Limit
              schema:
                type: integer
            X-RateLimit-Reset:
              description: >-
                Unix timestamp (seconds) when X-RateLimit-Remaining will next
                equal X-RateLimit-Limit
              schema:
                type: integer
        '400':
          content:
            application/json:
              schema:
                $ref: >-
                  #/components/schemas/github_com_trakrf_platform_backend_internal_models_errors.ErrorResponse
          description: Bad Request
        '401':
          content:
            application/json:
              schema:
                $ref: >-
                  #/components/schemas/github_com_trakrf_platform_backend_internal_models_errors.ErrorResponse
          description: Unauthorized
        '403':
          content:
            application/json:
              schema:
                $ref: >-
                  #/components/schemas/github_com_trakrf_platform_backend_internal_models_errors.ErrorResponse
          description: Forbidden
        '429':
          content:
            application/json:
              schema:
                $ref: >-
                  #/components/schemas/github_com_trakrf_platform_backend_internal_models_errors.ErrorResponse
          description: rate_limited
          headers:
            Retry-After:
              description: Seconds to wait before retrying
              schema:
                type: integer
      security:
        - APIKey:
            - scans:read
      summary: List current asset locations
      tags:
        - reports
  /api/v1/orgs/{id}/api-keys:
    get:
      operationId: api_keys.list
      parameters:
        - description: Organization id
          in: path
          name: id
          required: true
          schema:
            type: integer
        - description: max 200
          in: query
          name: limit
          schema:
            default: 50
            type: integer
        - description: min 0
          in: query
          name: offset
          schema:
            default: 0
            type: integer
      responses:
        '200':
          content:
            application/json:
              schema:
                $ref: >-
                  #/components/schemas/internal_handlers_orgs.ListAPIKeysResponse
          description: OK
        '400':
          content:
            application/json:
              schema:
                $ref: >-
                  #/components/schemas/github_com_trakrf_platform_backend_internal_models_errors.ErrorResponse
          description: Bad Request
        '401':
          content:
            application/json:
              schema:
                $ref: >-
                  #/components/schemas/github_com_trakrf_platform_backend_internal_models_errors.ErrorResponse
          description: Unauthorized
        '403':
          content:
            application/json:
              schema:
                $ref: >-
                  #/components/schemas/github_com_trakrf_platform_backend_internal_models_errors.ErrorResponse
          description: Forbidden
        '500':
          content:
            application/json:
              schema:
                $ref: >-
                  #/components/schemas/github_com_trakrf_platform_backend_internal_models_errors.ErrorResponse
          description: Internal Server Error
      security:
        - BearerAuth: []
        - APIKey:
            - keys:admin
      summary: List active API keys for an organization
      tags:
        - api-keys
    post:
      description: >-
        Mints an API-key JWT scoped to the target org. Accepts either
        session-admin or an API key with the keys:admin scope.
      operationId: api_keys.create
      parameters:
        - description: Organization id
          in: path
          name: id
          required: true
          schema:
            type: integer
      requestBody:
        content:
          application/json:
            schema:
              $ref: >-
                #/components/schemas/github_com_trakrf_platform_backend_internal_models_apikey.CreateAPIKeyRequest
        description: Key creation payload
        required: true
        x-originalParamName: request
      responses:
        '201':
          content:
            application/json:
              schema:
                $ref: >-
                  #/components/schemas/internal_handlers_orgs.CreateAPIKeyResponse
          description: Created
        '400':
          content:
            application/json:
              schema:
                $ref: >-
                  #/components/schemas/github_com_trakrf_platform_backend_internal_models_errors.ErrorResponse
          description: Bad Request
        '401':
          content:
            application/json:
              schema:
                $ref: >-
                  #/components/schemas/github_com_trakrf_platform_backend_internal_models_errors.ErrorResponse
          description: Unauthorized
        '403':
          content:
            application/json:
              schema:
                $ref: >-
                  #/components/schemas/github_com_trakrf_platform_backend_internal_models_errors.ErrorResponse
          description: Forbidden
        '409':
          content:
            application/json:
              schema:
                $ref: >-
                  #/components/schemas/github_com_trakrf_platform_backend_internal_models_errors.ErrorResponse
          description: Active-key cap reached
        '500':
          content:
            application/json:
              schema:
                $ref: >-
                  #/components/schemas/github_com_trakrf_platform_backend_internal_models_errors.ErrorResponse
          description: Internal Server Error
      security:
        - BearerAuth: []
        - APIKey:
            - keys:admin
      summary: Create a new API key for an organization
      tags:
        - api-keys
  /api/v1/orgs/{id}/api-keys/{key_id}:
    delete:
      operationId: api_keys.revoke
      parameters:
        - description: Organization id
          in: path
          name: id
          required: true
          schema:
            type: integer
        - description: Either the integer surrogate id or the UUID jti
          in: path
          name: key_id
          required: true
          schema:
            type: string
      responses:
        '204':
          description: No Content
        '400':
          content:
            application/json:
              schema:
                $ref: >-
                  #/components/schemas/github_com_trakrf_platform_backend_internal_models_errors.ErrorResponse
          description: Bad Request
        '401':
          content:
            application/json:
              schema:
                $ref: >-
                  #/components/schemas/github_com_trakrf_platform_backend_internal_models_errors.ErrorResponse
          description: Unauthorized
        '403':
          content:
            application/json:
              schema:
                $ref: >-
                  #/components/schemas/github_com_trakrf_platform_backend_internal_models_errors.ErrorResponse
          description: Forbidden
        '404':
          content:
            application/json:
              schema:
                $ref: >-
                  #/components/schemas/github_com_trakrf_platform_backend_internal_models_errors.ErrorResponse
          description: Not Found
        '500':
          content:
            application/json:
              schema:
                $ref: >-
                  #/components/schemas/github_com_trakrf_platform_backend_internal_models_errors.ErrorResponse
          description: Internal Server Error
      security:
        - BearerAuth: []
        - APIKey:
            - keys:admin
      summary: Revoke an API key
      tags:
        - api-keys
  /api/v1/orgs/me:
    get:
      description: >-
        Returns the organization scoped by the API key presented in
        Authorization. Intended as a lightweight health-check primitive for
        integrators verifying a key works end-to-end.
      operationId: orgs.me
      responses:
        '200':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/internal_handlers_orgs.GetOrgMeResponse'
          description: OK
        '401':
          content:
            application/json:
              schema:
                $ref: >-
                  #/components/schemas/github_com_trakrf_platform_backend_internal_models_errors.ErrorResponse
          description: Unauthorized
        '500':
          content:
            application/json:
              schema:
                $ref: >-
                  #/components/schemas/github_com_trakrf_platform_backend_internal_models_errors.ErrorResponse
          description: Internal server error
      security:
        - APIKey: []
      summary: Get the org associated with the authenticated API key
      tags:
        - orgs
servers:
  - description: Production
    url: https://app.trakrf.id
  - description: Preview (per-PR deploys)
    url: https://app.preview.trakrf.id
