> ## Documentation Index
> Fetch the complete documentation index at: https://docs.dottxt.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Additional Properties

> Control schema strictness by deciding where unknown keys are allowed.

`additionalProperties` controls whether fields not listed in `properties` are allowed. It can be set to either `true` or `false`. Setting it to `false` locks the schema to exactly the declared fields: the model cannot invent extra keys, and your application knows precisely what to expect.

This is one of the highest-leverage settings in production schemas. Without it, the model might add a helpful-looking `"notes"` field that no consumer knows how to handle, or a `"timestamp"` that conflicts with your own timestamping logic. These extra fields pass validation silently and cause bugs downstream.

The nuance is that strict everywhere isn't always right. Sometimes you need a flexible container, such as a `metadata` object for vendor-specific keys or an `extras` bag for forward compatibility. The pattern is: strict at the top level, flexible in one designated location.

## Use case

Audit logs that need a strict top-level structure for indexing and compliance, but a `metadata` object that can carry vendor-specific keys without schema changes.

## Schema pattern

<CodeGroup>
  ```json JSON Schema theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
  {
    "type": "object",
    "properties": {
      "event_id": { "type": "string" },
      "event_type": { "type": "string", "enum": ["login", "logout", "password_reset"] },
      "actor": {
        "type": "object",
        "properties": {
          "user_id": { "type": "string" },
          "ip": { "type": "string" }
        },
        "required": ["user_id", "ip"],
        "additionalProperties": false
      },
      "metadata": {
        "type": "object",
        "additionalProperties": {
          "type": ["string", "number", "boolean", "null"]
        }
      }
    },
    "required": ["event_id", "event_type", "actor", "metadata"],
    "additionalProperties": false
  }
  ```

  ```python Pydantic theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
  from typing import Literal
  from pydantic import BaseModel, ConfigDict

  class Actor(BaseModel):
      model_config = ConfigDict(extra="forbid")
      user_id: str
      ip: str

  class AuditEvent(BaseModel):
      model_config = ConfigDict(extra="forbid")
      event_id: str
      event_type: Literal["login", "logout", "password_reset"]
      actor: Actor
      metadata: dict[str, str | float | bool | None]
  ```

  ```typescript Zod theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
  import { z } from "zod";

  const actorSchema = z.object({
    user_id: z.string(),
    ip: z.string(),
  }).strict();

  const auditEventSchema = z.object({
    event_id: z.string(),
    event_type: z.enum(["login", "logout", "password_reset"]),
    actor: actorSchema,
    metadata: z.record(z.string(), z.union([z.string(), z.number(), z.boolean(), z.null()])),
  }).strict();
  ```
</CodeGroup>

## Example output

```json theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
{
  "event_id": "evt_6f1a",
  "event_type": "login",
  "actor": {
    "user_id": "usr_331",
    "ip": "203.0.113.10"
  },
  "metadata": {
    "device": "ios",
    "mfa": true,
    "attempt": 1
  }
}
```

## Why this works

The top-level object and the `actor` sub-object both have `additionalProperties: false`, so no unexpected fields can appear in the core structure. Your indexing pipeline knows exactly which fields exist and can map them directly to database columns or search indices.

The `metadata` object uses `additionalProperties: { "type": ["string", "number", "boolean", "null"] }`; it allows arbitrary keys, but constrains their values to primitive types. This prevents deeply nested or complex structures from sneaking into what should be a flat key-value bag. New metadata keys appear without schema changes, but they can't break your storage layer.

## Related docs

* [Object reference](/json-schema/reference/object)
* [Improve Your Schema](/json-schema/improve-your-schema)
