openapi: 3.0.3
info:
  title: VALOTEX Engine API
  version: 1.6.0
servers:
  - url: https://api.valotex.co.il
paths:
  /health:
    get:
      summary: Check API availability
      responses:
        '200': { description: API is available }
  /api/v1/dictionary:
    get:
      summary: Read active dictionary entries for one application
      parameters:
        - in: query
          name: app
          required: true
          schema: { type: string, enum: [client, admin, production] }
      responses:
        '200': { description: Filtered active dictionary }
        '400': { description: Invalid application name }
  /api/v1/client/session:
    get:
      summary: Read the authenticated customer session
      security: [{ firebaseUser: [] }]
      responses:
        '200': { description: Customer session and profiles }
    post:
      summary: Create or refresh the customer application profile
      security: [{ firebaseUser: [] }]
      responses:
        '200': { description: Customer session initialized }
  /api/v1/client/profile:
    put:
      summary: Save the authenticated customer profile
      security: [{ firebaseUser: [] }]
      responses:
        '200': { description: Profile saved }
  /api/v1/client/projects:
    get:
      summary: List projects owned by the authenticated customer
      security: [{ firebaseUser: [] }]
      responses:
        '200': { description: Customer projects }
    post:
      summary: Create a project with spaces, boxes and furniture items
      security: [{ firebaseUser: [] }]
      responses:
        '201': { description: Project created }
  /api/v1/client/projects/{id}/snapshot:
    get:
      summary: Read an owned project calculation snapshot
      security: [{ firebaseUser: [] }]
      responses:
        '200': { description: Project snapshot }
        '403': { description: Project belongs to another account }
  /api/v1/client/push-devices:
    post:
      summary: Register a browser push token
      security: [{ firebaseUser: [] }]
      responses:
        '201': { description: Push device registered }
    delete:
      summary: Remove a browser push token
      security: [{ firebaseUser: [] }]
      responses:
        '200': { description: Push device removed }
  /api/v1/admin/dashboard:
    get:
      summary: Read the administration data snapshot
      security: [{ firebaseAdmin: [] }]
      responses:
        '200': { description: Administration data }
  /api/v1/admin/customers:
    post:
      summary: Create a customer
      security: [{ firebaseAdmin: [] }]
      responses:
        '201': { description: Customer created }
  /api/v1/admin/customers/{id}:
    put:
      summary: Update a customer
      security: [{ firebaseAdmin: [] }]
      responses:
        '200': { description: Customer updated }
    delete:
      summary: Delete a customer and its project data
      security: [{ firebaseAdmin: [] }]
      responses:
        '200': { description: Customer deleted }
  /api/v1/production/dashboard:
    get:
      summary: Read the production data snapshot
      security: [{ firebaseUser: [] }]
      responses:
        '200': { description: Production data }
        '403': { description: Production role required }
  /api/v1/production/projects/{id}:
    put:
      summary: Update production fields on a project
      security: [{ firebaseUser: [] }]
      responses:
        '200': { description: Project updated }
  /api/v1/admin/dictionary:
    get:
      summary: Read the complete dictionary
      security: [{ firebaseAdmin: [] }]
      responses:
        '200': { description: Complete dictionary including inactive entries }
    post:
      summary: Create a dictionary entry
      security: [{ firebaseAdmin: [] }]
      requestBody: { $ref: '#/components/requestBodies/DictionaryItem' }
      responses:
        '201': { description: Entry created }
    put:
      summary: Replace and reconcile the complete dictionary
      security: [{ firebaseAdmin: [] }]
      responses:
        '200': { description: Dictionary synchronized }
  /api/v1/admin/dictionary/{id}:
    parameters:
      - in: path
        name: id
        required: true
        schema: { type: string }
    get:
      summary: Read one dictionary entry
      security: [{ firebaseAdmin: [] }]
      responses:
        '200': { description: Dictionary entry }
    put:
      summary: Update one dictionary entry
      security: [{ firebaseAdmin: [] }]
      requestBody: { $ref: '#/components/requestBodies/DictionaryItem' }
      responses:
        '200': { description: Entry updated }
    delete:
      summary: Permanently delete one dictionary entry
      security: [{ firebaseAdmin: [] }]
      responses:
        '200': { description: Entry deleted }
        '404': { description: Entry not found }
  /api/v1/drafts:
    post:
      summary: Create a calculation draft
      security: [{ firebaseUser: [] }]
      responses:
        '201': { description: Draft created }
  /api/v1/drafts/{draftId}:
    parameters:
      - in: path
        name: draftId
        required: true
        schema: { type: string }
    get:
      summary: Read a calculation draft
      security: [{ firebaseUser: [] }]
      responses:
        '200': { description: Draft returned }
        '404': { description: Draft not found }
    put:
      summary: Replace the project snapshot and invalidate its previous calculation
      security: [{ firebaseUser: [] }]
      responses:
        '200': { description: Draft updated and calculation marked pending }
        '409': { description: Released draft is locked }
  /api/v1/drafts/{draftId}/calculate:
    post:
      summary: Decompose all boxes and create sheet nesting in VALOTEX Engine
      description: All manufacturing calculations run on the server. The Engine compares X-led, Y-led and mixed X/Y nesting across multiple sort and placement strategies, then selects fewer sheets and less waste. Optional settings are toolDiameter, clearance and borderGap; defaults are 6, 1 and 5 mm. The client only submits project data and renders this response.
      security: [{ firebaseUser: [] }]
      parameters:
        - in: path
          name: draftId
          required: true
          schema: { type: string }
      responses:
        '200': { description: Complete parts list and nesting result persisted on the draft }
        '404': { description: Draft not found }
        '409': { description: Released draft is locked }
        '422': { description: A part is invalid or does not fit its material sheet }
  /api/v1/drafts/{draftId}/release:
    post:
      summary: Create an immutable manufacturing release from a completed calculation
      security: [{ firebaseUser: [] }]
      parameters:
        - in: path
          name: draftId
          required: true
          schema: { type: string }
      responses:
        '201': { description: Manufacturing release created }
        '409': { description: Calculation is incomplete }
components:
  securitySchemes:
    firebaseUser:
      type: http
      scheme: bearer
      bearerFormat: Firebase-ID-Token
    firebaseAdmin:
      type: http
      scheme: bearer
      bearerFormat: Firebase-ID-Token with admin permission
  requestBodies:
    DictionaryItem:
      required: true
      content:
        application/json:
          schema: { $ref: '#/components/schemas/DictionaryItem' }
  schemas:
    DictionaryItem:
      type: object
      required: [value, defaultValue, apps]
      properties:
        id: { type: string }
        value: { type: string }
        defaultValue: { type: string }
        description: { type: string }
        location: { type: string }
        locations: { type: array, items: { type: string } }
        apps: { type: array, items: { type: string, enum: [client, admin, production, all] } }
        active: { type: boolean }
