{
  "topic": "models",
  "path": [
    "models"
  ],
  "title": "models — entity model schema system",
  "synopsis": "A model is a named, versioned schema registered per tenant. Every entity in the system is an instance of exactly one model. Models are identified by `(entityName, modelVersion)`. The model ID is a deterministic UUID v5 derived from that key: `UUID.newSHA1(NameSpaceURL, \"{entityName}.{modelVersion}\")`.",
  "body": "# models\n\n## NAME\n\nmodels — entity model schema system: registration, lifecycle, import, export, and validation.\n\n## SYNOPSIS\n\n```\nGET    /api/model/\nGET    /api/model/export/{converter}/{entityName}/{modelVersion}\nPOST   /api/model/import/{dataFormat}/{converter}/{entityName}/{modelVersion}\nPOST   /api/model/validate/{entityName}/{modelVersion}\nDELETE /api/model/{entityName}/{modelVersion}\nPOST   /api/model/{entityName}/{modelVersion}/changeLevel/{changeLevel}\nPUT    /api/model/{entityName}/{modelVersion}/lock\nPUT    /api/model/{entityName}/{modelVersion}/unlock\nGET    /api/model/{entityName}/{modelVersion}/workflow/export\nPOST   /api/model/{entityName}/{modelVersion}/workflow/import\n```\n\nContext path prefix is `CYODA_CONTEXT_PATH` (default `/api`).\n\n## DESCRIPTION\n\nA model is a named, versioned schema registered per tenant. Every entity in the system is an instance of exactly one model. Models are identified by `(entityName, modelVersion)`. The model ID is a deterministic UUID v5 derived from that key: `UUID.newSHA1(NameSpaceURL, \"{entityName}.{modelVersion}\")`.\n\nModels have two lifecycle states: `UNLOCKED` and `LOCKED`. A `LOCKED` model blocks further imports. An `UNLOCKED` model accepts re-import and schema merging. Entities can only be created against a `LOCKED` model. Deletion is blocked while any entities reference the model.\n\nSchema inference is additive: importing sample data against an existing model merges the incoming schema with the stored one. The model's `changeLevel` field controls which structural changes are allowed during entity ingestion on a locked model.\n\n## ENDPOINTS\n\n**GET /api/model/**\n\nList all models for the authenticated tenant.\n\nResponse: `200 OK`, `application/json`, array of `EntityModelDto`.\n\n**POST /api/model/import/{dataFormat}/{converter}/{entityName}/{modelVersion}**\n\nImport or update a model schema from sample data. Body size limit: 10 MiB.\n\n- `dataFormat` (path): `JSON` or `XML`\n- `converter` (path): `SAMPLE_DATA` (only supported converter; `JSON_SCHEMA` and `SIMPLE_VIEW` are defined in the OpenAPI but return `400 BAD_REQUEST` in this implementation)\n- `entityName` (path): string — model name\n- `modelVersion` (path): int32 — model version number\n\nIf the model does not exist, it is created with state `UNLOCKED`. If it exists and is `UNLOCKED`, the incoming schema is merged (additive). If it exists and is `LOCKED`, returns `409 CONFLICT`.\n\nResponse: `200 OK`, `application/json`, UUID string — the model ID.\n\n**GET /api/model/export/{converter}/{entityName}/{modelVersion}**\n\nExport a model schema in the specified format.\n\n- `converter` (path): `JSON_SCHEMA` or `SIMPLE_VIEW`\n- `entityName` (path): string\n- `modelVersion` (path): int32\n\nResponse: `200 OK`, `application/json` — format depends on converter.\n\n**POST /api/model/validate/{entityName}/{modelVersion}**\n\nValidate a JSON payload against the model's schema. Returns a result object, not an HTTP error, on validation failure.\n\n- `entityName` (path): string\n- `modelVersion` (path): int32\n\nRequest body: any JSON object.\n\nResponse: `200 OK`, `application/json`, `EntityModelActionResultDto`.\n\n**DELETE /api/model/{entityName}/{modelVersion}**\n\nDelete a model. Blocked if the model is `LOCKED` or if any entities reference it (entity count > 0).\n\nResponse: `200 OK`, `application/json`, `EntityModelActionResultDto` on success. `409 CONFLICT` if entities exist.\n\n**POST /api/model/{entityName}/{modelVersion}/changeLevel/{changeLevel}**\n\nSet or update the change level on a model. Meaningful for locked models; unlocked models always allow all changes.\n\n- `changeLevel` (path): `ARRAY_LENGTH`, `ARRAY_ELEMENTS`, `TYPE`, or `STRUCTURAL`\n\nChange levels are hierarchical (most restrictive to most permissive):\n\n- `ARRAY_LENGTH` — permits only increases in uni-type array width\n- `ARRAY_ELEMENTS` — allows multi-type array changes without adding new types\n- `TYPE` — permits modifications to existing types\n- `STRUCTURAL` — allows fundamental model changes including new fields\n\nResponse: `200 OK`, `application/json`, `EntityModelActionResultDto`.\n\n**PUT /api/model/{entityName}/{modelVersion}/lock**\n\nLock a model. The model must be `UNLOCKED`. Returns `409 CONFLICT` if already locked.\n\nResponse: `200 OK`, `application/json`, `EntityModelActionResultDto`.\n\n**PUT /api/model/{entityName}/{modelVersion}/unlock**\n\nUnlock a model. The model must be `LOCKED` and have zero associated entities. Returns `409 CONFLICT` if entities exist or model is not locked.\n\nResponse: `200 OK`, `application/json`, `EntityModelActionResultDto`.\n\n**GET /api/model/{entityName}/{modelVersion}/workflow/export**\n\nExport all workflow configurations for the model. Returns `404 WORKFLOW_NOT_FOUND` if no workflows exist.\n\nResponse: `200 OK`, `application/json`:\n\n```json\n{\n  \"entityName\": \"nobel-prize\",\n  \"modelVersion\": 1,\n  \"workflows\": []\n}\n```\n\n**POST /api/model/{entityName}/{modelVersion}/workflow/import**\n\nImport or replace workflow configurations for the model. See `workflows` topic.\n\n## REQUEST SCHEMAS\n\n**EntityModelDto** (returned by `GET /api/model/`):\n\n```json\n{\n  \"id\": \"31134900-d9cb-11ee-b913-ae468cd3ed16\",\n  \"modelName\": \"nobel-prize\",\n  \"modelVersion\": 1,\n  \"currentState\": \"LOCKED\",\n  \"modelUpdateDate\": \"2025-08-02T13:31:48.141053-07:00\"\n}\n```\n\n- `id` — UUID (deterministic v5, derived from name+version)\n- `modelName` — string\n- `modelVersion` — int32\n- `currentState` — `\"LOCKED\"` or `\"UNLOCKED\"`\n- `modelUpdateDate` — RFC 3339 timestamp, nullable\n\n**EntityModelActionResultDto** (returned by lock, unlock, delete, changeLevel, validate):\n\n```json\n{\n  \"success\": true,\n  \"message\": \"Model nobel-prize:1 locked\",\n  \"modelId\": \"cee334fa-c0ac-11f0-ba79-ae468cd3ed16\",\n  \"modelKey\": {\n    \"name\": \"nobel-prize\",\n    \"version\": 1\n  }\n}\n```\n\n- `success` — boolean\n- `message` — human-readable result string\n- `modelId` — UUID\n- `modelKey.name` — string\n- `modelKey.version` — int32\n\n**Import request body** (sample data, JSON format):\n\n```json\n{\n  \"category\": \"physics\",\n  \"year\": \"2024\",\n  \"laureates\": [\n    {\n      \"firstname\": \"John\",\n      \"surname\": \"Hopfield\",\n      \"id\": \"1037\",\n      \"motivation\": \"for foundational discoveries\",\n      \"share\": \"2\"\n    }\n  ]\n}\n```\n\nThe importer walks the JSON structure and infers a typed schema. Subsequent imports are merged additively.\n\n**Export — SIMPLE_VIEW format**:\n\n```json\n{\n  \"currentState\": \"LOCKED\",\n  \"model\": {\n    \"$\": {\n      \"#.laureates\": \"OBJECT\",\n      \".category\": \"STRING\",\n      \".year\": \"STRING\"\n    },\n    \"$.laureates[*]\": {\n      \"#\": \"ARRAY_ELEMENT\",\n      \".firstname\": \"STRING\",\n      \".id\": \"STRING\",\n      \".motivation\": \"STRING\",\n      \".share\": \"STRING\",\n      \".surname\": \"STRING\"\n    }\n  }\n}\n```\n\nThe `\"$\"` bucket includes a `\"#.fieldname\": \"OBJECT\"` entry for each array field in the root object. The `\"$.fieldname[*]\"` bucket contains the array element schema with `\"#\": \"ARRAY_ELEMENT\"` as a type marker.\n\n**Export — JSON_SCHEMA format**:\n\n```json\n{\n  \"currentState\": \"LOCKED\",\n  \"model\": {\n    \"type\": \"object\",\n    \"properties\": {\n      \"category\": { \"type\": \"string\" },\n      \"year\": { \"type\": \"string\" },\n      \"laureates\": {\n        \"type\": \"array\",\n        \"items\": {\n          \"type\": \"object\",\n          \"properties\": {\n            \"firstname\": { \"type\": \"string\" },\n            \"share\": { \"type\": \"string\" },\n            \"id\": { \"type\": \"string\" },\n            \"surname\": { \"type\": \"string\" },\n            \"motivation\": { \"type\": \"string\" }\n          }\n        }\n      }\n    }\n  }\n}\n```\n\n## LIFECYCLE\n\nA model moves between two states:\n\n- `UNLOCKED` — initial state after first import; re-import is permitted; entities cannot be created\n- `LOCKED` — entities can be created; re-import is blocked; change-level controls in-flight schema extension\n\nTransitions:\n\n- `UNLOCKED` → `LOCKED` via `PUT /model/{name}/{version}/lock`\n- `LOCKED` → `UNLOCKED` via `PUT /model/{name}/{version}/unlock` (only when entity count is zero)\n\nThe `changeLevel` field controls schema evolution on locked models. When set, entity ingestion that introduces new structure triggers an additive schema extension (delta computed via `schema.Diff`, appended via `ModelStore.ExtendSchema`, committed with the entity transaction).\n\n## ERRORS\n\n- `errors.MODEL_NOT_FOUND` — `404` — model does not exist for the given name and version\n- `errors.CONFLICT` — `409` — import blocked (model is locked), lock failed (already locked), unlock failed (entities exist or model not locked), delete failed (entities exist)\n- `errors.VALIDATION_FAILED` — `400` — workflow import validation failed (static analysis)\n- `errors.BAD_REQUEST` — `400` — unsupported converter, invalid changeLevel, malformed body\n\n## EXAMPLES\n\n**Import a model from sample JSON:**\n\n```\ncurl -s -X POST \\\n  -H \"Authorization: Bearer $TOKEN\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"category\":\"physics\",\"year\":\"2024\",\"laureates\":[{\"firstname\":\"John\",\"surname\":\"Hopfield\",\"id\":\"1037\"}]}' \\\n  \"http://localhost:8080/api/model/import/JSON/SAMPLE_DATA/nobel-prize/1\"\n```\n\nResponse: `\"1d1e1b10-1155-11f0-bcd5-ae468cd3ed16\"`\n\n**Lock the model:**\n\n```\ncurl -s -X PUT \\\n  -H \"Authorization: Bearer $TOKEN\" \\\n  \"http://localhost:8080/api/model/nobel-prize/1/lock\"\n```\n\n**Set change level (allow structural evolution on locked model):**\n\n```\ncurl -s -X POST \\\n  -H \"Authorization: Bearer $TOKEN\" \\\n  \"http://localhost:8080/api/model/nobel-prize/1/changeLevel/STRUCTURAL\"\n```\n\n**List all models:**\n\n```\ncurl -s -H \"Authorization: Bearer $TOKEN\" \\\n  \"http://localhost:8080/api/model/\"\n```\n\n**Export as SIMPLE_VIEW:**\n\n```\ncurl -s -H \"Authorization: Bearer $TOKEN\" \\\n  \"http://localhost:8080/api/model/export/SIMPLE_VIEW/nobel-prize/1\"\n```\n\n**Validate a payload against the model:**\n\n```\ncurl -s -X POST \\\n  -H \"Authorization: Bearer $TOKEN\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"category\":\"physics\",\"year\":\"2024\"}' \\\n  \"http://localhost:8080/api/model/validate/nobel-prize/1\"\n```\n\n**Delete a model (must be unlocked and have zero entities):**\n\n```\ncurl -s -X DELETE \\\n  -H \"Authorization: Bearer $TOKEN\" \\\n  \"http://localhost:8080/api/model/nobel-prize/1\"\n```\n\n## SEE ALSO\n\n- crud\n- workflows\n- search\n- errors.MODEL_NOT_FOUND\n- errors.VALIDATION_FAILED\n- errors.CONFLICT\n- openapi\n",
  "sections": [
    {
      "name": "NAME",
      "body": "models — entity model schema system: registration, lifecycle, import, export, and validation."
    },
    {
      "name": "SYNOPSIS",
      "body": "```\nGET    /api/model/\nGET    /api/model/export/{converter}/{entityName}/{modelVersion}\nPOST   /api/model/import/{dataFormat}/{converter}/{entityName}/{modelVersion}\nPOST   /api/model/validate/{entityName}/{modelVersion}\nDELETE /api/model/{entityName}/{modelVersion}\nPOST   /api/model/{entityName}/{modelVersion}/changeLevel/{changeLevel}\nPUT    /api/model/{entityName}/{modelVersion}/lock\nPUT    /api/model/{entityName}/{modelVersion}/unlock\nGET    /api/model/{entityName}/{modelVersion}/workflow/export\nPOST   /api/model/{entityName}/{modelVersion}/workflow/import\n```\n\nContext path prefix is `CYODA_CONTEXT_PATH` (default `/api`)."
    },
    {
      "name": "DESCRIPTION",
      "body": "A model is a named, versioned schema registered per tenant. Every entity in the system is an instance of exactly one model. Models are identified by `(entityName, modelVersion)`. The model ID is a deterministic UUID v5 derived from that key: `UUID.newSHA1(NameSpaceURL, \"{entityName}.{modelVersion}\")`.\n\nModels have two lifecycle states: `UNLOCKED` and `LOCKED`. A `LOCKED` model blocks further imports. An `UNLOCKED` model accepts re-import and schema merging. Entities can only be created against a `LOCKED` model. Deletion is blocked while any entities reference the model.\n\nSchema inference is additive: importing sample data against an existing model merges the incoming schema with the stored one. The model's `changeLevel` field controls which structural changes are allowed during entity ingestion on a locked model."
    },
    {
      "name": "ENDPOINTS",
      "body": "**GET /api/model/**\n\nList all models for the authenticated tenant.\n\nResponse: `200 OK`, `application/json`, array of `EntityModelDto`.\n\n**POST /api/model/import/{dataFormat}/{converter}/{entityName}/{modelVersion}**\n\nImport or update a model schema from sample data. Body size limit: 10 MiB.\n\n- `dataFormat` (path): `JSON` or `XML`\n- `converter` (path): `SAMPLE_DATA` (only supported converter; `JSON_SCHEMA` and `SIMPLE_VIEW` are defined in the OpenAPI but return `400 BAD_REQUEST` in this implementation)\n- `entityName` (path): string — model name\n- `modelVersion` (path): int32 — model version number\n\nIf the model does not exist, it is created with state `UNLOCKED`. If it exists and is `UNLOCKED`, the incoming schema is merged (additive). If it exists and is `LOCKED`, returns `409 CONFLICT`.\n\nResponse: `200 OK`, `application/json`, UUID string — the model ID.\n\n**GET /api/model/export/{converter}/{entityName}/{modelVersion}**\n\nExport a model schema in the specified format.\n\n- `converter` (path): `JSON_SCHEMA` or `SIMPLE_VIEW`\n- `entityName` (path): string\n- `modelVersion` (path): int32\n\nResponse: `200 OK`, `application/json` — format depends on converter.\n\n**POST /api/model/validate/{entityName}/{modelVersion}**\n\nValidate a JSON payload against the model's schema. Returns a result object, not an HTTP error, on validation failure.\n\n- `entityName` (path): string\n- `modelVersion` (path): int32\n\nRequest body: any JSON object.\n\nResponse: `200 OK`, `application/json`, `EntityModelActionResultDto`.\n\n**DELETE /api/model/{entityName}/{modelVersion}**\n\nDelete a model. Blocked if the model is `LOCKED` or if any entities reference it (entity count > 0).\n\nResponse: `200 OK`, `application/json`, `EntityModelActionResultDto` on success. `409 CONFLICT` if entities exist.\n\n**POST /api/model/{entityName}/{modelVersion}/changeLevel/{changeLevel}**\n\nSet or update the change level on a model. Meaningful for locked models; unlocked models always allow all changes.\n\n- `changeLevel` (path): `ARRAY_LENGTH`, `ARRAY_ELEMENTS`, `TYPE`, or `STRUCTURAL`\n\nChange levels are hierarchical (most restrictive to most permissive):\n\n- `ARRAY_LENGTH` — permits only increases in uni-type array width\n- `ARRAY_ELEMENTS` — allows multi-type array changes without adding new types\n- `TYPE` — permits modifications to existing types\n- `STRUCTURAL` — allows fundamental model changes including new fields\n\nResponse: `200 OK`, `application/json`, `EntityModelActionResultDto`.\n\n**PUT /api/model/{entityName}/{modelVersion}/lock**\n\nLock a model. The model must be `UNLOCKED`. Returns `409 CONFLICT` if already locked.\n\nResponse: `200 OK`, `application/json`, `EntityModelActionResultDto`.\n\n**PUT /api/model/{entityName}/{modelVersion}/unlock**\n\nUnlock a model. The model must be `LOCKED` and have zero associated entities. Returns `409 CONFLICT` if entities exist or model is not locked.\n\nResponse: `200 OK`, `application/json`, `EntityModelActionResultDto`.\n\n**GET /api/model/{entityName}/{modelVersion}/workflow/export**\n\nExport all workflow configurations for the model. Returns `404 WORKFLOW_NOT_FOUND` if no workflows exist.\n\nResponse: `200 OK`, `application/json`:\n\n```json\n{\n  \"entityName\": \"nobel-prize\",\n  \"modelVersion\": 1,\n  \"workflows\": []\n}\n```\n\n**POST /api/model/{entityName}/{modelVersion}/workflow/import**\n\nImport or replace workflow configurations for the model. See `workflows` topic."
    },
    {
      "name": "REQUEST SCHEMAS",
      "body": "**EntityModelDto** (returned by `GET /api/model/`):\n\n```json\n{\n  \"id\": \"31134900-d9cb-11ee-b913-ae468cd3ed16\",\n  \"modelName\": \"nobel-prize\",\n  \"modelVersion\": 1,\n  \"currentState\": \"LOCKED\",\n  \"modelUpdateDate\": \"2025-08-02T13:31:48.141053-07:00\"\n}\n```\n\n- `id` — UUID (deterministic v5, derived from name+version)\n- `modelName` — string\n- `modelVersion` — int32\n- `currentState` — `\"LOCKED\"` or `\"UNLOCKED\"`\n- `modelUpdateDate` — RFC 3339 timestamp, nullable\n\n**EntityModelActionResultDto** (returned by lock, unlock, delete, changeLevel, validate):\n\n```json\n{\n  \"success\": true,\n  \"message\": \"Model nobel-prize:1 locked\",\n  \"modelId\": \"cee334fa-c0ac-11f0-ba79-ae468cd3ed16\",\n  \"modelKey\": {\n    \"name\": \"nobel-prize\",\n    \"version\": 1\n  }\n}\n```\n\n- `success` — boolean\n- `message` — human-readable result string\n- `modelId` — UUID\n- `modelKey.name` — string\n- `modelKey.version` — int32\n\n**Import request body** (sample data, JSON format):\n\n```json\n{\n  \"category\": \"physics\",\n  \"year\": \"2024\",\n  \"laureates\": [\n    {\n      \"firstname\": \"John\",\n      \"surname\": \"Hopfield\",\n      \"id\": \"1037\",\n      \"motivation\": \"for foundational discoveries\",\n      \"share\": \"2\"\n    }\n  ]\n}\n```\n\nThe importer walks the JSON structure and infers a typed schema. Subsequent imports are merged additively.\n\n**Export — SIMPLE_VIEW format**:\n\n```json\n{\n  \"currentState\": \"LOCKED\",\n  \"model\": {\n    \"$\": {\n      \"#.laureates\": \"OBJECT\",\n      \".category\": \"STRING\",\n      \".year\": \"STRING\"\n    },\n    \"$.laureates[*]\": {\n      \"#\": \"ARRAY_ELEMENT\",\n      \".firstname\": \"STRING\",\n      \".id\": \"STRING\",\n      \".motivation\": \"STRING\",\n      \".share\": \"STRING\",\n      \".surname\": \"STRING\"\n    }\n  }\n}\n```\n\nThe `\"$\"` bucket includes a `\"#.fieldname\": \"OBJECT\"` entry for each array field in the root object. The `\"$.fieldname[*]\"` bucket contains the array element schema with `\"#\": \"ARRAY_ELEMENT\"` as a type marker.\n\n**Export — JSON_SCHEMA format**:\n\n```json\n{\n  \"currentState\": \"LOCKED\",\n  \"model\": {\n    \"type\": \"object\",\n    \"properties\": {\n      \"category\": { \"type\": \"string\" },\n      \"year\": { \"type\": \"string\" },\n      \"laureates\": {\n        \"type\": \"array\",\n        \"items\": {\n          \"type\": \"object\",\n          \"properties\": {\n            \"firstname\": { \"type\": \"string\" },\n            \"share\": { \"type\": \"string\" },\n            \"id\": { \"type\": \"string\" },\n            \"surname\": { \"type\": \"string\" },\n            \"motivation\": { \"type\": \"string\" }\n          }\n        }\n      }\n    }\n  }\n}\n```"
    },
    {
      "name": "LIFECYCLE",
      "body": "A model moves between two states:\n\n- `UNLOCKED` — initial state after first import; re-import is permitted; entities cannot be created\n- `LOCKED` — entities can be created; re-import is blocked; change-level controls in-flight schema extension\n\nTransitions:\n\n- `UNLOCKED` → `LOCKED` via `PUT /model/{name}/{version}/lock`\n- `LOCKED` → `UNLOCKED` via `PUT /model/{name}/{version}/unlock` (only when entity count is zero)\n\nThe `changeLevel` field controls schema evolution on locked models. When set, entity ingestion that introduces new structure triggers an additive schema extension (delta computed via `schema.Diff`, appended via `ModelStore.ExtendSchema`, committed with the entity transaction)."
    },
    {
      "name": "ERRORS",
      "body": "- `errors.MODEL_NOT_FOUND` — `404` — model does not exist for the given name and version\n- `errors.CONFLICT` — `409` — import blocked (model is locked), lock failed (already locked), unlock failed (entities exist or model not locked), delete failed (entities exist)\n- `errors.VALIDATION_FAILED` — `400` — workflow import validation failed (static analysis)\n- `errors.BAD_REQUEST` — `400` — unsupported converter, invalid changeLevel, malformed body"
    },
    {
      "name": "EXAMPLES",
      "body": "**Import a model from sample JSON:**\n\n```\ncurl -s -X POST \\\n  -H \"Authorization: Bearer $TOKEN\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"category\":\"physics\",\"year\":\"2024\",\"laureates\":[{\"firstname\":\"John\",\"surname\":\"Hopfield\",\"id\":\"1037\"}]}' \\\n  \"http://localhost:8080/api/model/import/JSON/SAMPLE_DATA/nobel-prize/1\"\n```\n\nResponse: `\"1d1e1b10-1155-11f0-bcd5-ae468cd3ed16\"`\n\n**Lock the model:**\n\n```\ncurl -s -X PUT \\\n  -H \"Authorization: Bearer $TOKEN\" \\\n  \"http://localhost:8080/api/model/nobel-prize/1/lock\"\n```\n\n**Set change level (allow structural evolution on locked model):**\n\n```\ncurl -s -X POST \\\n  -H \"Authorization: Bearer $TOKEN\" \\\n  \"http://localhost:8080/api/model/nobel-prize/1/changeLevel/STRUCTURAL\"\n```\n\n**List all models:**\n\n```\ncurl -s -H \"Authorization: Bearer $TOKEN\" \\\n  \"http://localhost:8080/api/model/\"\n```\n\n**Export as SIMPLE_VIEW:**\n\n```\ncurl -s -H \"Authorization: Bearer $TOKEN\" \\\n  \"http://localhost:8080/api/model/export/SIMPLE_VIEW/nobel-prize/1\"\n```\n\n**Validate a payload against the model:**\n\n```\ncurl -s -X POST \\\n  -H \"Authorization: Bearer $TOKEN\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"category\":\"physics\",\"year\":\"2024\"}' \\\n  \"http://localhost:8080/api/model/validate/nobel-prize/1\"\n```\n\n**Delete a model (must be unlocked and have zero entities):**\n\n```\ncurl -s -X DELETE \\\n  -H \"Authorization: Bearer $TOKEN\" \\\n  \"http://localhost:8080/api/model/nobel-prize/1\"\n```"
    },
    {
      "name": "SEE ALSO",
      "body": "- crud\n- workflows\n- search\n- errors.MODEL_NOT_FOUND\n- errors.VALIDATION_FAILED\n- errors.CONFLICT\n- openapi"
    }
  ],
  "see_also": [
    "crud",
    "workflows",
    "search",
    "errors.MODEL_NOT_FOUND",
    "errors.VALIDATION_FAILED",
    "errors.CONFLICT",
    "openapi"
  ],
  "stability": "stable",
  "actions": []
}
