{
  "openapi": "3.1.0",
  "info": {
    "title": "HMK API",
    "version": "1.0.0",
    "description": "Workspace projects, activity and print requests. Requests require HMK review; no automatic printer start, pricing or inventory API in this increment."
  },
  "servers": [
    {
      "url": "https://app.hmk.dk/api/v1"
    }
  ],
  "paths": {
    "/workspaces": {
      "get": {
        "operationId": "list_workspaces",
        "summary": "List workspaces available to this delegated user. Only the workspace selected during connection is returned.",
        "parameters": [],
        "security": [
          {
            "hmkOAuth": [
              "projects:read"
            ]
          }
        ],
        "responses": {
          "200": {
            "description": "Success. Shared HMK record(s).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/Workspace"
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid input"
          },
          "401": {
            "description": "Missing, expired or revoked token"
          },
          "403": {
            "description": "Missing workspace access or scope"
          },
          "409": {
            "description": "Revision conflict or reused identifier with different input"
          }
        }
      }
    },
    "/workspaces/{workspaceId}/projects": {
      "get": {
        "operationId": "list_projects",
        "summary": "List shared projects with concurrency revision. The same records are visible in the HMK app.",
        "parameters": [
          {
            "name": "workspaceId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 80
            }
          }
        ],
        "security": [
          {
            "hmkOAuth": [
              "projects:read"
            ]
          }
        ],
        "responses": {
          "200": {
            "description": "Success. Shared HMK record(s).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/Project"
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid input"
          },
          "401": {
            "description": "Missing, expired or revoked token"
          },
          "403": {
            "description": "Missing workspace access or scope"
          },
          "409": {
            "description": "Revision conflict or reused identifier with different input"
          }
        }
      },
      "post": {
        "operationId": "create_project",
        "summary": "Create a shared hardware project, not CAD geometry. Supply a new UUID as id; reuse identical input/id on retry. New projects are not released for print.",
        "parameters": [
          {
            "name": "workspaceId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 80
            }
          }
        ],
        "security": [
          {
            "hmkOAuth": [
              "projects:read",
              "projects:write"
            ]
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "id": {
                    "type": "string",
                    "pattern": "^[a-zA-Z0-9-]{16,64}$"
                  },
                  "title": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 150
                  },
                  "description": {
                    "type": "string",
                    "maxLength": 4000
                  }
                },
                "required": [
                  "id",
                  "title",
                  "description"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Success. Shared HMK record(s).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Project"
                }
              }
            }
          },
          "400": {
            "description": "Invalid input"
          },
          "401": {
            "description": "Missing, expired or revoked token"
          },
          "403": {
            "description": "Missing workspace access or scope"
          },
          "409": {
            "description": "Revision conflict or reused identifier with different input"
          }
        }
      }
    },
    "/workspaces/{workspaceId}/projects/{id}": {
      "get": {
        "operationId": "get_project",
        "summary": "Get a project and latest revision before editing.",
        "parameters": [
          {
            "name": "workspaceId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 80
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 80
            }
          }
        ],
        "security": [
          {
            "hmkOAuth": [
              "projects:read"
            ]
          }
        ],
        "responses": {
          "200": {
            "description": "Success. Shared HMK record(s).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Project"
                }
              }
            }
          },
          "400": {
            "description": "Invalid input"
          },
          "401": {
            "description": "Missing, expired or revoked token"
          },
          "403": {
            "description": "Missing workspace access or scope"
          },
          "409": {
            "description": "Revision conflict or reused identifier with different input"
          }
        }
      },
      "patch": {
        "operationId": "update_project",
        "summary": "Update title/description using expectedRevision from get_project. On conflict fetch latest and resolve with the user; never blindly overwrite. Model editing is not supported.",
        "parameters": [
          {
            "name": "workspaceId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 80
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 80
            }
          }
        ],
        "security": [
          {
            "hmkOAuth": [
              "projects:read",
              "projects:write"
            ]
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "title": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 150
                  },
                  "description": {
                    "type": "string",
                    "maxLength": 4000
                  },
                  "expectedRevision": {
                    "type": "integer",
                    "minimum": 0,
                    "maximum": 9007199254740991
                  }
                },
                "required": [
                  "title",
                  "description",
                  "expectedRevision"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Success. Shared HMK record(s).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Project"
                }
              }
            }
          },
          "400": {
            "description": "Invalid input"
          },
          "401": {
            "description": "Missing, expired or revoked token"
          },
          "403": {
            "description": "Missing workspace access or scope"
          },
          "409": {
            "description": "Revision conflict or reused identifier with different input"
          }
        }
      }
    },
    "/workspaces/{workspaceId}/projects/{projectId}/configurations": {
      "get": {
        "operationId": "list_configurations",
        "summary": "Get valid POS options and manufacturing readiness. No price or delivery promise is available yet.",
        "parameters": [
          {
            "name": "workspaceId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 80
            }
          },
          {
            "name": "projectId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 80
            }
          }
        ],
        "security": [
          {
            "hmkOAuth": [
              "projects:read"
            ]
          }
        ],
        "responses": {
          "200": {
            "description": "Success. Shared HMK record(s).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Configurations"
                }
              }
            }
          },
          "400": {
            "description": "Invalid input"
          },
          "401": {
            "description": "Missing, expired or revoked token"
          },
          "403": {
            "description": "Missing workspace access or scope"
          },
          "409": {
            "description": "Revision conflict or reused identifier with different input"
          }
        }
      }
    },
    "/workspaces/{workspaceId}/orders": {
      "post": {
        "operationId": "submit_print_order",
        "summary": "Submit a physical-production request to HMK for review, not direct printer start. Obtain user confirmation of project, version, geometry and quantity first. Reuse requestId on retry. Price and completion time are not yet quoted.",
        "parameters": [
          {
            "name": "workspaceId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 80
            }
          }
        ],
        "security": [
          {
            "hmkOAuth": [
              "projects:read",
              "orders:write"
            ]
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "projectId": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 80
                  },
                  "angle": {
                    "type": "integer",
                    "minimum": -9007199254740991,
                    "maximum": 9007199254740991
                  },
                  "tube": {
                    "type": "integer",
                    "minimum": -9007199254740991,
                    "maximum": 9007199254740991
                  },
                  "base": {
                    "type": "string"
                  },
                  "quantity": {
                    "type": "integer",
                    "minimum": 1,
                    "maximum": 100
                  },
                  "note": {
                    "type": "string",
                    "maxLength": 2000
                  },
                  "requestId": {
                    "type": "string",
                    "pattern": "^[a-zA-Z0-9-]{16,64}$"
                  },
                  "version": {
                    "type": "string",
                    "const": "loby-pos-0.6.2"
                  }
                },
                "required": [
                  "projectId",
                  "angle",
                  "tube",
                  "base",
                  "quantity",
                  "note",
                  "requestId",
                  "version"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Success. Shared HMK record(s).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Order"
                }
              }
            }
          },
          "400": {
            "description": "Invalid input"
          },
          "401": {
            "description": "Missing, expired or revoked token"
          },
          "403": {
            "description": "Missing workspace access or scope"
          },
          "409": {
            "description": "Revision conflict or reused identifier with different input"
          }
        }
      },
      "get": {
        "operationId": "list_print_orders",
        "summary": "List shared print orders and their actual HMK status.",
        "parameters": [
          {
            "name": "workspaceId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 80
            }
          }
        ],
        "security": [
          {
            "hmkOAuth": [
              "projects:read",
              "orders:read"
            ]
          }
        ],
        "responses": {
          "200": {
            "description": "Success. Shared HMK record(s).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/Order"
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid input"
          },
          "401": {
            "description": "Missing, expired or revoked token"
          },
          "403": {
            "description": "Missing workspace access or scope"
          },
          "409": {
            "description": "Revision conflict or reused identifier with different input"
          }
        }
      }
    },
    "/workspaces/{workspaceId}/orders/{id}": {
      "get": {
        "operationId": "get_order_status",
        "summary": "Get one order. REQUESTED is not PRINTING; no ETA is reported unless production has one.",
        "parameters": [
          {
            "name": "workspaceId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 80
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 80
            }
          }
        ],
        "security": [
          {
            "hmkOAuth": [
              "projects:read",
              "orders:read"
            ]
          }
        ],
        "responses": {
          "200": {
            "description": "Success. Shared HMK record(s).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Order"
                }
              }
            }
          },
          "400": {
            "description": "Invalid input"
          },
          "401": {
            "description": "Missing, expired or revoked token"
          },
          "403": {
            "description": "Missing workspace access or scope"
          },
          "409": {
            "description": "Revision conflict or reused identifier with different input"
          }
        }
      }
    },
    "/workspaces/{workspaceId}/activity": {
      "get": {
        "operationId": "list_activity",
        "summary": "Read append-only workspace activity with actor, client, changes and time. Paginated, 50 entries; use nextCursor as before.",
        "parameters": [
          {
            "name": "workspaceId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 80
            }
          },
          {
            "name": "before",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "maxLength": 100
            }
          }
        ],
        "security": [
          {
            "hmkOAuth": [
              "projects:read",
              "activity:read"
            ]
          }
        ],
        "responses": {
          "200": {
            "description": "Success. Shared HMK record(s).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "items": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Activity"
                      }
                    },
                    "nextCursor": {
                      "type": [
                        "string",
                        "null"
                      ]
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid input"
          },
          "401": {
            "description": "Missing, expired or revoked token"
          },
          "403": {
            "description": "Missing workspace access or scope"
          },
          "409": {
            "description": "Revision conflict or reused identifier with different input"
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "Workspace": {
        "type": "object",
        "required": [
          "id",
          "name",
          "role"
        ],
        "properties": {
          "id": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "role": {
            "type": "string"
          }
        }
      },
      "Project": {
        "type": "object",
        "required": [
          "id",
          "title",
          "description",
          "version",
          "kind",
          "workstreams",
          "revision",
          "updatedBy",
          "updatedAt"
        ],
        "properties": {
          "id": {
            "type": "string"
          },
          "title": {
            "type": "string"
          },
          "description": {
            "type": "string"
          },
          "version": {
            "type": "string"
          },
          "kind": {
            "enum": [
              "POS",
              "HARDWARE"
            ]
          },
          "revision": {
            "type": "integer",
            "minimum": 0
          },
          "updatedBy": {
            "type": [
              "string",
              "null"
            ]
          },
          "updatedAt": {
            "type": [
              "string",
              "null"
            ]
          },
          "workstreams": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "id": {
                  "type": "string"
                },
                "title": {
                  "type": "string"
                },
                "revision": {
                  "type": "string"
                },
                "status": {
                  "type": "string"
                },
                "detail": {
                  "type": "string"
                }
              }
            }
          }
        }
      },
      "Order": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "workspaceId": {
            "type": "string"
          },
          "projectId": {
            "type": "string"
          },
          "projectTitle": {
            "type": "string"
          },
          "version": {
            "type": "string"
          },
          "angle": {
            "type": "integer"
          },
          "tube": {
            "type": "integer"
          },
          "base": {
            "type": "string"
          },
          "quantity": {
            "type": "integer"
          },
          "note": {
            "type": "string"
          },
          "createdBy": {
            "type": "string"
          },
          "createdAt": {
            "type": "string"
          },
          "status": {
            "type": "string"
          },
          "updatedBy": {
            "type": [
              "string",
              "null"
            ]
          },
          "updatedAt": {
            "type": [
              "string",
              "null"
            ]
          },
          "createdVia": {
            "type": [
              "string",
              "null"
            ]
          },
          "clientName": {
            "type": [
              "string",
              "null"
            ]
          },
          "clientId": {
            "type": [
              "string",
              "null"
            ]
          }
        }
      },
      "Activity": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "action": {
            "type": "string"
          },
          "entityId": {
            "type": "string"
          },
          "actorEmail": {
            "type": "string"
          },
          "actorName": {
            "type": "string"
          },
          "source": {
            "type": "string"
          },
          "clientId": {
            "type": "string"
          },
          "clientName": {
            "type": "string"
          },
          "at": {
            "type": "string"
          },
          "before": {
            "type": "string"
          },
          "after": {
            "type": "string"
          }
        }
      },
      "Configurations": {
        "type": "object",
        "required": [
          "ordering",
          "automaticPrint"
        ],
        "properties": {
          "version": {
            "type": "string"
          },
          "angles": {
            "type": "array",
            "items": {
              "type": "integer"
            }
          },
          "tubes": {
            "type": "array",
            "items": {
              "type": "integer"
            }
          },
          "bases": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "ordering": {
            "enum": [
              "HMK_REVIEW",
              "NOT_RELEASED"
            ]
          },
          "automaticPrint": {
            "const": false
          },
          "price": {
            "type": "null"
          },
          "estimatedCompletion": {
            "type": "null"
          }
        }
      },
      "Error": {
        "type": "object",
        "properties": {
          "error": {
            "type": "string"
          },
          "message": {
            "type": "string"
          }
        }
      }
    },
    "securitySchemes": {
      "hmkOAuth": {
        "type": "oauth2",
        "flows": {
          "authorizationCode": {
            "authorizationUrl": "https://app.hmk.dk/oauth/authorize",
            "tokenUrl": "https://app.hmk.dk/oauth/token",
            "scopes": {
              "projects:read": "Read shared projects",
              "projects:write": "Create/edit projects",
              "orders:read": "Read orders",
              "orders:write": "Submit print requests",
              "activity:read": "Read activity"
            }
          }
        }
      }
    }
  }
}
