---
title: "Check a draft without publishing it"
method: POST
path: "/v1/skill-drafts/{draft_id}/validate"
tags: ["skill-drafts"]
---

# Check a draft without publishing it

`POST /v1/skill-drafts/{draft_id}/validate`

## Request

- Base URL: `https://api.patricia.app` (the document declares no server; this is the origin it was published from)
- URL: `https://api.patricia.app/v1/skill-drafts/{draft_id}/validate`
- Auth: HTTP bearer

Compile the draft through the same platform gates a real save runs, and additionally check the manifest against the files this draft actually carries — so a reference or script you declared but never added is caught here rather than at publish. Writes no version. Always 200 (the result is in the body).

## Path parameters

- `draft_id` string, uuid, required

## Headers

- `X-Tenant-Id` string, nullable

## Response `200`

Successful Response

- DraftValidationResponse: The result of validating a draft — friendly errors for the editor. Always 200.
  - `valid` boolean, required
  - `errors` string[]
  - `warnings` string[]: Worth telling the author, but not blocking: a warning never makes `valid` false.
  - `slug` string, nullable
  - `title` string, nullable
  - `missing_files` string[]: Paths the manifest declares that this draft does not carry — an editor points at the file list.
  - `dropped_files` string[]: Paths this draft carries that the manifest does not declare. Publishing stores only what the manifest names, so these would be lost without being mentioned anywhere.

## Other responses

- `400`: Bad request
- `401`: Unauthorized
- `403`: Forbidden. Inspect response body `code` for the specific reason (for example: PERMISSION_DENIED, EMAIL_NOT_VERIFIED, TENANT_ACCESS_REQUIRED, ROLE_UNRESOLVED)
- `409`: Conflict
- `422`: Validation error

---

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