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

# Schema Enforcement

> Validate, auto-repair, and semantically correct LLM outputs against JSON schemas

# Schema Enforcement

Schema Enforcement ensures your LLM outputs conform to a defined JSON schema. Perf validates responses, auto-repairs common issues, applies semantic corrections (like fixing negative prices), and guarantees you receive properly structured data.

## Why Schema Enforcement?

LLMs are unreliable at producing consistent JSON:

* Missing required fields
* Wrong data types (string instead of number)
* Extra fields not in schema
* Malformed JSON syntax
* Markdown code blocks wrapping JSON

Perf's Schema Enforcement:

* **Validates** outputs against your JSON Schema
* **Auto-repairs** common issues (type coercion, format fixes)
* **Semantic correction** fixes domain-specific errors (negative prices, invalid ratings)
* **Retries** with better prompts if validation fails
* **Guarantees** schema-compliant responses

## Using Schemas in Requests

### Inline Schema

Pass a JSON Schema directly in your request:

```bash theme={null}
curl -X POST https://api.withperf.pro/v1/chat \
  -H "Authorization: Bearer pk_live_abc123" \
  -H "Content-Type: application/json" \
  -d '{
    "messages": [
      {
        "role": "user",
        "content": "Extract contact info: John Smith, john@example.com, 555-1234"
      }
    ],
    "schema": {
      "type": "object",
      "properties": {
        "name": { "type": "string" },
        "email": { "type": "string", "format": "email" },
        "phone": { "type": "string" }
      },
      "required": ["name", "email"]
    }
  }'
```

### Schema by ID

Reference a saved schema by ID or slug:

```bash theme={null}
curl -X POST https://api.withperf.pro/v1/chat \
  -H "Authorization: Bearer pk_live_abc123" \
  -H "Content-Type: application/json" \
  -d '{
    "messages": [{"role": "user", "content": "Extract contact info..."}],
    "schema_id": "contact-extraction"
  }'
```

### Project Default Schema

Set a default schema for your project in the Dashboard. All requests without an explicit schema will use it.

## Schema Parameters

| Parameter       | Type    | Description                                                  |
| --------------- | ------- | ------------------------------------------------------------ |
| `schema`        | object  | Inline JSON Schema (Draft 2020-12)                           |
| `schema_id`     | string  | ID or slug of a saved schema                                 |
| `schema_strict` | boolean | Disable auto-repair, fail on any mismatch (default: `false`) |

## Response

When schema enforcement is active, responses include validation metadata:

```json theme={null}
{
  "choices": [{
    "message": {
      "content": "{\"name\": \"John Smith\", \"email\": \"john@example.com\", \"phone\": \"555-1234\"}"
    }
  }],
  "perf": {
    "schema_validation": {
      "enabled": true,
      "passed": true,
      "repaired": false,
      "schema_source": "inline"
    }
  }
}
```

### Validation Fields

| Field           | Type    | Description                                 |
| --------------- | ------- | ------------------------------------------- |
| `enabled`       | boolean | Schema validation was active                |
| `passed`        | boolean | Final output passed validation              |
| `repaired`      | boolean | Auto-repair was applied                     |
| `schema_source` | string  | `inline`, `schema_id`, or `project_default` |

## Auto-Repair

When `schema_strict: false` (default), Perf attempts to repair common issues:

| Issue                     | Repair Action                     |
| ------------------------- | --------------------------------- |
| String instead of number  | Parse to number (`"42"` → `42`)   |
| Number instead of string  | Convert to string (`42` → `"42"`) |
| String instead of boolean | Parse (`"true"` → `true`)         |
| Markdown code blocks      | Extract JSON from `json ... `     |
| Extra whitespace          | Trim and normalize                |
| Missing optional fields   | Leave as undefined                |

### Example: Auto-Repair in Action

LLM returns:

````
Here's the extracted data:
```json
{"name": "John", "age": "25"}
````

````

With schema requiring `age` as number, Perf:
1. Extracts JSON from markdown
2. Coerces `"25"` → `25`
3. Returns valid JSON

## Semantic Validation

Go beyond structural validation with semantic type hints. Add `x-semantic-type` to your schema fields to auto-correct common LLM errors like negative prices, out-of-range ratings, and invalid dates.

### Using x-semantic-type

```json
{
  "type": "object",
  "properties": {
    "price": {
      "type": "number",
      "x-semantic-type": "currency_positive"
    },
    "rating": {
      "type": "number",
      "x-semantic-type": "rating_1_5"
    },
    "customer_age": {
      "type": "integer",
      "x-semantic-type": "human_age"
    }
  }
}
````

### Supported Semantic Types

| Type                      | Description                        | Auto-Correction            |
| ------------------------- | ---------------------------------- | -------------------------- |
| `currency_positive`       | Prices, amounts (must be positive) | `-$999` → `$999`           |
| `currency_allow_negative` | Values that can be negative        | Validates magnitude only   |
| `human_age`               | Person ages (0-130)                | Clamps to valid range      |
| `percentage`              | Percentages (0-100 or 0-1)         | Normalizes scale           |
| `rating_1_5`              | 5-star ratings                     | `12` → `5` (clamps to max) |
| `rating_1_10`             | 10-point ratings                   | Clamps to 1-10 range       |
| `email`                   | Email addresses                    | Format validation          |
| `url`                     | URLs                               | Format validation          |
| `date_past`               | Historical dates                   | Flags future dates         |
| `date_future`             | Upcoming dates                     | Flags past dates           |

### Example: Semantic Correction in Action

Request with semantic types:

```bash theme={null}
curl -X POST https://api.withperf.pro/v1/chat \
  -H "Authorization: Bearer pk_live_abc123" \
  -H "Content-Type: application/json" \
  -d '{
    "messages": [{
      "role": "user",
      "content": "Extract: iPhone 15 Pro costs -$999, rating 12/5 stars"
    }],
    "response_format": {
      "type": "json_schema",
      "json_schema": {
        "name": "product",
        "schema": {
          "type": "object",
          "properties": {
            "name": { "type": "string" },
            "price": { "type": "number", "x-semantic-type": "currency_positive" },
            "rating": { "type": "number", "x-semantic-type": "rating_1_5" }
          },
          "required": ["name", "price", "rating"]
        }
      }
    }
  }'
```

Response with corrections:

```json theme={null}
{
  "choices": [{
    "message": {
      "content": "{\"name\": \"iPhone 15 Pro\", \"price\": 999, \"rating\": 5}"
    }
  }],
  "perf": {
    "semantic_validation": {
      "result": "corrected",
      "corrections": [
        {
          "field": "price",
          "original": -999,
          "corrected": 999,
          "reason": "currency_positive values must be non-negative",
          "confidence": 1.0
        },
        {
          "field": "rating",
          "original": 12,
          "corrected": 5,
          "reason": "rating_1_5 clamped to maximum value",
          "confidence": 1.0
        }
      ],
      "latency_ms": 3.2
    }
  }
}
```

### Semantic Validation Response Fields

| Field         | Type   | Description                        |
| ------------- | ------ | ---------------------------------- |
| `result`      | string | `pass`, `corrected`, or `failed`   |
| `corrections` | array  | List of auto-corrections applied   |
| `warnings`    | array  | Non-blocking issues detected       |
| `latency_ms`  | number | Validation latency in milliseconds |

## Strict Mode

Enable strict mode to disable auto-repair:

```json theme={null}
{
  "messages": [...],
  "schema": {...},
  "schema_strict": true
}
```

In strict mode:

* No type coercion
* No format repairs
* Validation fails on any mismatch
* Returns error if validation fails after retries

## Managing Schemas

### Create Schema (Dashboard API)

```bash theme={null}
curl -X POST https://api.withperf.pro/v1/dashboard/projects/{projectId}/schemas \
  -H "Authorization: Bearer <clerk_jwt>" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Contact Extraction",
    "slug": "contact-extraction",
    "description": "Schema for extracting contact information",
    "schema": {
      "type": "object",
      "properties": {
        "name": { "type": "string" },
        "email": { "type": "string", "format": "email" },
        "phone": { "type": "string" }
      },
      "required": ["name", "email"]
    },
    "is_default": false
  }'
```

### List Schemas

```bash theme={null}
curl https://api.withperf.pro/v1/dashboard/projects/{projectId}/schemas \
  -H "Authorization: Bearer <clerk_jwt>"
```

### Test Schema

Test a schema against sample data:

```bash theme={null}
curl -X POST https://api.withperf.pro/v1/dashboard/projects/{projectId}/schemas/test \
  -H "Authorization: Bearer <clerk_jwt>" \
  -H "Content-Type: application/json" \
  -d '{
    "schema": {
      "type": "object",
      "properties": {
        "name": { "type": "string" }
      },
      "required": ["name"]
    },
    "data": {"name": "John"}
  }'
```

## Supported JSON Schema Features

Perf supports JSON Schema Draft 2020-12 with these features:

### Types

* `string`, `number`, `integer`, `boolean`, `null`
* `object`, `array`

### String Formats

* `email`, `uri`, `date`, `date-time`, `uuid`

### Validation Keywords

* `required`, `properties`, `additionalProperties`
* `minLength`, `maxLength`, `pattern`
* `minimum`, `maximum`, `exclusiveMinimum`, `exclusiveMaximum`
* `minItems`, `maxItems`, `uniqueItems`
* `enum`, `const`

### Composition

* `allOf`, `anyOf`, `oneOf`
* `$ref` (local references only)

## Best Practices

### 1. Keep Schemas Simple

```json theme={null}
{
  "type": "object",
  "properties": {
    "sentiment": { "enum": ["positive", "negative", "neutral"] },
    "confidence": { "type": "number", "minimum": 0, "maximum": 1 }
  },
  "required": ["sentiment", "confidence"]
}
```

### 2. Use Descriptive Names

Add `title` and `description` to help the LLM understand:

```json theme={null}
{
  "type": "object",
  "title": "Product Review Analysis",
  "properties": {
    "rating": {
      "type": "integer",
      "minimum": 1,
      "maximum": 5,
      "description": "Star rating from 1-5"
    }
  }
}
```

### 3. Prefer Enums for Categories

```json theme={null}
{
  "category": {
    "type": "string",
    "enum": ["bug", "feature", "question", "documentation"]
  }
}
```

### 4. Set Reasonable Defaults

Use `default` for optional fields:

```json theme={null}
{
  "properties": {
    "priority": {
      "type": "string",
      "enum": ["low", "medium", "high"],
      "default": "medium"
    }
  }
}
```

## Error Handling

### Validation Failed

If validation fails after retries:

```json theme={null}
{
  "error": {
    "type": "schema_validation_failed",
    "message": "Output failed schema validation after 2 attempts",
    "details": {
      "errors": [
        { "path": "/email", "message": "must match format \"email\"" }
      ]
    }
  }
}
```

### Invalid Schema

If your schema is invalid:

```json theme={null}
{
  "error": {
    "type": "invalid_schema",
    "message": "Schema validation error: 'type' must be a string"
  }
}
```

## Plan Limits

| Tier       | Max Schemas | Auto-Repair | Semantic Validation |
| ---------- | ----------- | ----------- | ------------------- |
| Starter    | 3           | No          | No                  |
| Pro        | 10          | Yes         | Yes                 |
| Growth     | 50          | Yes         | Yes                 |
| Enterprise | Unlimited   | Yes         | Yes                 |

## Related Endpoints

* [Chat API](./chat) - Use schemas with chat completions
* [Streaming API](./streaming) - Schema validation with streaming
* [Logs API](./logs) - View validation history
