---
title: "Declare a metadata schema"
method: POST
path: "/v1/projects/{project_id}/metadata-schemas"
tags: ["Metadata Schemas"]
---

# Declare a metadata schema

`POST /v1/projects/{project_id}/metadata-schemas`

## Request

- Base URL: `https://api.naturali.ai`
- URL: `https://api.naturali.ai/v1/projects/{project_id}/metadata-schemas`
- Auth: one of:
  - HTTP bearer
  - OAuth 2 (authorization code, authorization URL `https://api.naturali.ai/authorize`, token URL `https://api.naturali.ai/token`, scopes: `mcp:access`)

Declares what `metadata` must satisfy for one resource type under one selector. A document is selected by `path_prefix`, matched on a path boundary: `/reports` covers `/reports/q1.txt` and never `/reports-archive/q1.txt`.

The schema is compiled here, so one JSON Schema cannot parse is refused rather than stored — a stored one would be a rule that silently governs nothing. One selector has one schema per resource type; a second declaration of the same one is `409 NAME_CONFLICT`. The reserved root `/.system` cannot be governed: a platform-written document carries no caller metadata.

## Request body

- object
  - `resource_type` 'document', required: The resource whose metadata this declaration governs. A type appears here once its write path reads the registry, so a declaration always has a door that enforces it.
  - `path_prefix` string: The selector a `document` declaration must carry: the directory it governs.
  - `schema` object, required: A JSON Schema. Its keywords are its own vocabulary and are stored as written.

## Response `201`

The declaration

- MetadataSchemaRecord
  - `id` string: Public ID (mdschema_ prefix)
  - `project_id` string
  - `resource_type` 'document': The resource whose metadata this declaration governs.
  - `path_prefix` string: The selector, in the field its resource type is addressed by. A document's is the directory it is filed under.
  - `schema` object: The declared JSON Schema, as written.
  - `created_at` string, date-time
  - `updated_at` string, date-time

## Other responses

- `400`: Bad Request — unknown `resource_type`, a missing or unusable selector, the reserved root, or a schema that is not valid JSON Schema
- `401`: Unauthorized
- `403`: Forbidden
- `409`: Conflict — this selector is already declared for this type

---

[API](https://skmtc.dev/naturali/apis/naturali-ai-api.md) · [All operations](https://skmtc.dev/naturali/apis/naturali-ai-api/llms.txt) · [OpenAPI document](https://skmtc.dev/naturali/apis/naturali-ai-api/revisions/e4905b78f422?raw)
