# Create metadata property

Define a new property on this object type, scoped to the calling team. Search the existing properties first (GET this path with `term`) and reuse a match instead of defining a second property for the same fact. Pass `list_id` in the body to scope the definition to one list/app; without it the property is workspace-global and appears on every list. A name already used in that scope, an explicitly requested slug already taken, or a slug that a shared property already owns all return 409 naming the definition to use instead. The property's display format is resolved from `type` automatically — pass `role_id` only to override it. For `select_str` and `multiselect_str` types you may pre-seed the choices via `options`.

**Endpoint:** `POST /v2/prism/{teamId}/{objectType}/properties`  
**Operation ID:** `createMetadataProperty`  
**Server:** `https://developers.micro.so`  
**Security:** `[{"apiKey":[]}]`

## Parameters

```json
[
  {
    "name": "teamId",
    "in": "path",
    "required": true,
    "schema": {
      "type": "string",
      "format": "uuid"
    }
  },
  {
    "name": "objectType",
    "in": "path",
    "required": true,
    "schema": {
      "$ref": "#/components/schemas/ObjectType"
    }
  },
  {
    "$ref": "#/components/parameters/IdempotencyKey"
  }
]
```

## Request body

```json
{
  "required": true,
  "content": {
    "application/json": {
      "schema": {
        "$ref": "#/components/schemas/PropertyDefinitionCreate"
      }
    }
  }
}
```

## Responses

```json
{
  "201": {
    "description": "Property created",
    "headers": {
      "x-request-id": {
        "$ref": "#/components/headers/XRequestId"
      },
      "idempotent-replay": {
        "$ref": "#/components/headers/IdempotentReplay"
      }
    },
    "content": {
      "application/json": {
        "schema": {
          "$ref": "#/components/schemas/PropertyDefinition"
        }
      }
    }
  },
  "400": {
    "$ref": "#/components/responses/BadRequest"
  },
  "401": {
    "$ref": "#/components/responses/Unauthorized"
  },
  "403": {
    "$ref": "#/components/responses/Forbidden"
  },
  "409": {
    "$ref": "#/components/responses/Conflict"
  },
  "500": {
    "$ref": "#/components/responses/InternalError"
  }
}
```

## Referenced components

```json
{
  "securitySchemes": {
    "apiKey": {
      "type": "apiKey",
      "in": "header",
      "name": "x-api-key",
      "description": "Public API key generated from Micro settings. Sent as the `x-api-key` header and validated by AWS API Gateway in front of the service."
    }
  },
  "schemas": {
    "ObjectType": {
      "type": "string",
      "description": "Object types that support CRUD, query, list, and per-type property metadata. `GET /v2/prism/{teamId}/properties` (list-all) also returns definitions for pipeline-owned types that are not in this set — including `message`, `thread`, and `linkedin_thread`. Those types are not queryable. Contacts expose `last_email` as a `ref_message`; you cannot query `message` to follow it.",
      "enum": [
        "comment",
        "deal",
        "engagement",
        "identity",
        "ai_chat_thread",
        "ai_chat_message",
        "agent_site",
        "document",
        "action",
        "event",
        "organization",
        "contact"
      ]
    },
    "PropertyDefinitionCreate": {
      "type": "object",
      "description": "New property definition. Check for an existing property first (GET the same path with `term`) and reuse it rather than defining a near-duplicate — writes address properties by slug, so two definitions sharing a slug leave no addressable winner. For `select_str`/`multiselect_str` types you may pre-seed choices via `options`.",
      "required": [
        "type",
        "name"
      ],
      "properties": {
        "type": {
          "$ref": "#/components/schemas/PropertyType"
        },
        "name": {
          "type": "string",
          "description": "Human-readable name, unique within the scope the definition is created in. A name already taken in that scope returns 409; the message names the existing definition's id, slug and type so you can write to it instead."
        },
        "slug": {
          "type": "string",
          "description": "URL-safe identifier. When omitted it defaults to a slugified `name` and is disambiguated with a numeric suffix on conflict. When supplied explicitly it is treated as part of your write contract and is never silently renamed — a collision returns 409 instead."
        },
        "icon": {
          "type": [
            "string",
            "null"
          ]
        },
        "list_id": {
          "type": [
            "string",
            "null"
          ],
          "format": "uuid",
          "description": "Scopes the definition to one list/app. Omit it only for a property that genuinely belongs to the whole workspace: a definition created without `list_id` is workspace-global and surfaces on every list of this object type."
        },
        "role_id": {
          "type": [
            "string",
            "null"
          ],
          "format": "uuid",
          "description": "Optional display format for the property, drawn from the workspace's property roles. Omit it and the canonical role for `type` is applied (plain text, plain number, checkbox). Supply it only to pick a narrower format such as email, URL or currency; the role's data type must match `type`."
        },
        "required": {
          "type": "boolean",
          "description": "When true, records must carry a non-empty value for this property on create. Defaults to false.",
          "default": false
        },
        "options": {
          "type": "array",
          "description": "Only honored when `type` is `select_str` or `multiselect_str`.",
          "items": {
            "type": "object",
            "required": [
              "value"
            ],
            "properties": {
              "value": {
                "type": "string"
              },
              "slug": {
                "type": "string"
              },
              "color_scheme": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "sort_index": {
                "type": [
                  "integer",
                  "null"
                ]
              },
              "icon": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "description": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "option_group": {
                "type": [
                  "string",
                  "null"
                ]
              }
            },
            "additionalProperties": false
          }
        }
      },
      "additionalProperties": false
    },
    "PropertyDefinition": {
      "type": "object",
      "description": "Definition for a single property on an object type. Definitions with team_id and crm_id null are shared defaults; values may be scoped to a team and/or list (crm).",
      "required": [
        "id",
        "slug",
        "type"
      ],
      "properties": {
        "id": {
          "type": "string",
          "format": "uuid"
        },
        "slug": {
          "type": "string"
        },
        "name": {
          "type": [
            "string",
            "null"
          ]
        },
        "type": {
          "$ref": "#/components/schemas/PropertyType"
        },
        "team_id": {
          "type": [
            "string",
            "null"
          ],
          "format": "uuid"
        },
        "crm_id": {
          "type": [
            "string",
            "null"
          ],
          "format": "uuid",
          "description": "Identifier of the list this definition is scoped to, when applicable."
        },
        "list_id": {
          "type": [
            "string",
            "null"
          ],
          "format": "uuid",
          "description": "Canonical identifier of the list this definition is scoped to."
        },
        "native": {
          "type": "boolean"
        },
        "locked": {
          "type": "boolean"
        },
        "alias": {
          "type": [
            "string",
            "null"
          ],
          "enum": [
            "app_stage",
            null
          ],
          "description": "Reserved alias naming this definition, or null. `app_stage` marks the list pipeline stage definition. Resolve stages by this field rather than by name, slug, or team_id: a superseded native `status` definition can coexist with the pipeline one and is otherwise identical on the wire."
        },
        "required": {
          "type": "boolean",
          "description": "When true, records of this object type must carry a non-empty value for this property on create, and a patch may not clear it."
        },
        "role_id": {
          "type": [
            "string",
            "null"
          ],
          "format": "uuid",
          "description": "The property's display format. Always populated on definitions created through this API; a null here means the definition predates that and will render as an unknown format until it is patched."
        },
        "options": {
          "type": "array",
          "description": "Present only for select_str and multiselect_str types.",
          "items": {
            "$ref": "#/components/schemas/PropertyOption"
          }
        }
      },
      "additionalProperties": false
    },
    "PropertyType": {
      "type": "string",
      "description": "Storage type for a property definition. Determines which per-type table holds the values, and which display formats the property can take.",
      "enum": [
        "num",
        "str",
        "bool",
        "date",
        "text",
        "byte",
        "select_str",
        "multi_str",
        "multiselect_str",
        "jsonb",
        "ref_identity",
        "ref_user",
        "ref_organization",
        "ref_contact",
        "ref_thread",
        "ref_message",
        "ref_event",
        "ref_account",
        "ref_ai_chat_thread",
        "ref_ai_chat_message",
        "multiref_ai_chat_message",
        "multiref_agent_site",
        "multiref_action",
        "multiref_comment",
        "multiref_contact",
        "multiref_label",
        "multiref_thread",
        "multiref_messages",
        "multiref_document",
        "multiref_identity",
        "multiref_organization",
        "multiref_engagement",
        "multiref_attendee",
        "multiref_meeting_entry",
        "multiref_read_receipt",
        "multiref_account",
        "multiref_source"
      ]
    },
    "PropertyOption": {
      "type": "object",
      "description": "An enabled option for a select_str or multiselect_str property definition.",
      "required": [
        "id",
        "slug"
      ],
      "properties": {
        "id": {
          "type": "string",
          "format": "uuid"
        },
        "slug": {
          "type": "string"
        },
        "value": {
          "type": [
            "string",
            "null"
          ],
          "description": "Display value for the option."
        },
        "color_scheme": {
          "type": [
            "string",
            "null"
          ]
        },
        "sort_index": {
          "type": [
            "integer",
            "null"
          ]
        },
        "icon": {
          "type": [
            "string",
            "null"
          ]
        },
        "description": {
          "type": [
            "string",
            "null"
          ]
        },
        "option_group": {
          "type": [
            "string",
            "null"
          ]
        },
        "list_id": {
          "type": [
            "string",
            "null"
          ],
          "format": "uuid"
        },
        "crm_id": {
          "type": [
            "string",
            "null"
          ],
          "format": "uuid",
          "deprecated": true
        }
      },
      "additionalProperties": false
    },
    "Error": {
      "type": "object",
      "description": "Canonical JSON error envelope for every non-2xx v2 API response. `error.code` is the machine-readable error code, `error.message` is the human-readable summary, and `error.request_id` identifies the request for support. When supplied, `error.errors` contains field-level validation issues.",
      "required": [
        "error"
      ],
      "properties": {
        "error": {
          "type": "object",
          "required": [
            "code",
            "message",
            "request_id"
          ],
          "properties": {
            "code": {
              "type": "string",
              "description": "Stable machine-readable code. Branch on this, not on the HTTP status, to handle specific failure modes.",
              "example": "invalid_request"
            },
            "message": {
              "type": "string",
              "description": "Human-readable summary suitable for logs. Not localized; do not display verbatim to end users."
            },
            "request_id": {
              "type": [
                "string",
                "null"
              ],
              "description": "Echo of the x-request-id response header. Include in support requests."
            },
            "errors": {
              "type": "array",
              "description": "Optional structured field-level validation issues when the server provides them.",
              "items": {
                "type": "object",
                "properties": {
                  "field": {
                    "type": "string",
                    "description": "JSON path of the offending property (e.g. \".body.default.email\")."
                  },
                  "message": {
                    "type": "string"
                  },
                  "code": {
                    "type": "string",
                    "description": "Validator-specific code (e.g. \"required.openapi.validation\")."
                  }
                },
                "required": [
                  "message"
                ]
              }
            },
            "details": {
              "type": "object",
              "description": "Optional bag of error-specific context. Shape varies by code; clients should treat fields as opaque unless documented."
            }
          }
        }
      }
    }
  },
  "parameters": {
    "IdempotencyKey": {
      "name": "Idempotency-Key",
      "in": "header",
      "required": false,
      "description": "A unique key (UUID or any opaque string up to 255 chars) for an authenticated POST, PUT, or PATCH request. The server retains the initial claim for 24 hours and replays a completed non-5xx response only when the method, path, and request body all match. Reusing a non-expired key with a different method, path, or body returns 409 `idempotency_key_mismatch`; reusing it after expiry returns 409 `idempotency_key_stale`, so use a new key. Replays include the `idempotent-replay: true` response header.",
      "schema": {
        "type": "string",
        "minLength": 1,
        "maxLength": 255
      }
    }
  },
  "headers": {
    "XRequestId": {
      "description": "Correlation ID. Echoed from the request `x-request-id` header when supplied, otherwise generated. Include in support requests.",
      "schema": {
        "type": "string"
      }
    },
    "IdempotentReplay": {
      "description": "Present and set to `true` when this response is a cached replay of an earlier request with the same `Idempotency-Key`. Absent on first execution.",
      "schema": {
        "type": "string",
        "enum": [
          "true"
        ]
      }
    }
  },
  "responses": {
    "BadRequest": {
      "description": "Request validation failed. Inspect `error.errors` for field-level details.",
      "headers": {
        "x-request-id": {
          "$ref": "#/components/headers/XRequestId"
        }
      },
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "Unauthorized": {
      "description": "Missing or invalid credentials. API Gateway maps a missing or invalid `x-api-key` to HTTP 401 with this envelope (including `request_id`). A 403 here means the key was accepted but the caller is not permitted.",
      "headers": {
        "x-request-id": {
          "$ref": "#/components/headers/XRequestId"
        }
      },
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "Forbidden": {
      "description": "Authenticated but not permitted to perform this action.",
      "headers": {
        "x-request-id": {
          "$ref": "#/components/headers/XRequestId"
        }
      },
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "Conflict": {
      "description": "Request conflicts with current state (e.g., duplicate or stale write).",
      "headers": {
        "x-request-id": {
          "$ref": "#/components/headers/XRequestId"
        }
      },
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "InternalError": {
      "description": "Unexpected server error. Retry with backoff; report `request_id` if persistent.",
      "headers": {
        "x-request-id": {
          "$ref": "#/components/headers/XRequestId"
        }
      },
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    }
  }
}
```
