{
    "openapi": "3.1.2",
    "info": {
        "title": "p3n API",
        "version": "v1",
        "description": "The p3n API: AI detection and writing skills over HTTP. Up to 10 calls an hour work without a key; with a key, calls are billed per use. Guide, examples and pricing: https://p3n.si/docs"
    },
    "servers": [
        {
            "url": "https://api.p3n.si/v1",
            "description": "Production"
        }
    ],
    "paths": {
        "/me": {
            "get": {
                "operationId": "me",
                "description": "The key you called with and your balance. Needs an API key.",
                "summary": "Your account",
                "tags": [
                    "Account"
                ],
                "responses": {
                    "200": {
                        "description": "",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "email": {
                                            "type": "string"
                                        },
                                        "balance_usd": {
                                            "type": "string"
                                        },
                                        "key": {
                                            "type": "object",
                                            "properties": {
                                                "name": {
                                                    "type": "string"
                                                },
                                                "prefix": {
                                                    "type": "string"
                                                }
                                            },
                                            "required": [
                                                "name",
                                                "prefix"
                                            ]
                                        }
                                    },
                                    "required": [
                                        "email",
                                        "balance_usd",
                                        "key"
                                    ]
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "An error",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "message": {
                                            "type": "string",
                                            "description": "Error overview.",
                                            "examples": [
                                                "This endpoint needs an API key. Send Authorization: Bearer p3n_..."
                                            ]
                                        }
                                    },
                                    "required": [
                                        "message"
                                    ]
                                }
                            }
                        }
                    },
                    "429": {
                        "$ref": "#/components/responses/FreeLimit"
                    }
                },
                "parameters": [
                    {
                        "$ref": "#/components/parameters/X-P3N-Client"
                    }
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ]
            }
        },
        "/runs/{run}": {
            "get": {
                "operationId": "run.show",
                "description": "Poll a background run (202 answers point here) until `status` is `succeeded` or `failed`.",
                "summary": "Get a run",
                "tags": [
                    "Runs"
                ],
                "parameters": [
                    {
                        "name": "run",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "string"
                        }
                    },
                    {
                        "$ref": "#/components/parameters/X-P3N-Client"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "The run, with its output once it has finished.",
                        "headers": {
                            "X-Free-Limit": {
                                "$ref": "#/components/headers/X-Free-Limit"
                            },
                            "X-Free-Remaining": {
                                "$ref": "#/components/headers/X-Free-Remaining"
                            },
                            "X-Free-Reset": {
                                "$ref": "#/components/headers/X-Free-Reset"
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Run"
                                }
                            }
                        }
                    },
                    "404": {
                        "$ref": "#/components/responses/ModelNotFoundException"
                    },
                    "429": {
                        "$ref": "#/components/responses/FreeLimit"
                    }
                },
                "security": [
                    {
                        "apiKey": []
                    },
                    {
                        "__PHP_Incomplete_Class_Name": "stdClass"
                    }
                ]
            }
        },
        "/skills": {
            "get": {
                "operationId": "skill.index",
                "description": "Every skill the API runs, with its endpoint.",
                "summary": "List skills",
                "tags": [
                    "Account"
                ],
                "responses": {
                    "200": {
                        "description": "",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "type": "array",
                                            "items": {
                                                "type": "object",
                                                "properties": {
                                                    "slug": {
                                                        "type": "string"
                                                    },
                                                    "name": {
                                                        "type": "string"
                                                    },
                                                    "description": {
                                                        "type": "string"
                                                    },
                                                    "parent": {
                                                        "type": "string"
                                                    },
                                                    "sessions": {
                                                        "type": "boolean"
                                                    },
                                                    "endpoint": {
                                                        "type": "string"
                                                    }
                                                },
                                                "required": [
                                                    "slug",
                                                    "name",
                                                    "description",
                                                    "parent",
                                                    "sessions",
                                                    "endpoint"
                                                ]
                                            }
                                        }
                                    },
                                    "required": [
                                        "data"
                                    ]
                                }
                            }
                        }
                    },
                    "429": {
                        "$ref": "#/components/responses/FreeLimit"
                    }
                },
                "parameters": [
                    {
                        "$ref": "#/components/parameters/X-P3N-Client"
                    }
                ],
                "security": [
                    {
                        "apiKey": []
                    },
                    {
                        "__PHP_Incomplete_Class_Name": "stdClass"
                    }
                ]
            }
        },
        "/detect": {
            "post": {
                "operationId": "skills.detect",
                "summary": "AI Detection",
                "description": "Was this written by a person or a model?\n\nRuns in the background (202) when `async` is true or the text is over 20,000 characters. Details: https://p3n.si/skills/detect",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "required": [
                                    "text"
                                ],
                                "properties": {
                                    "text": {
                                        "type": "string",
                                        "minLength": 40,
                                        "maxLength": 200000
                                    },
                                    "options": {
                                        "type": "object",
                                        "properties": {
                                            "model": {
                                                "type": "string",
                                                "enum": [
                                                    "luna",
                                                    "haiku"
                                                ],
                                                "default": "luna",
                                                "description": "The model that reads the text (judge and LLM-read patterns)."
                                            },
                                            "version": {
                                                "type": "string",
                                                "description": "Pin a published detector version for reproducible results. Default: the latest.",
                                                "enum": [
                                                    "detect-v1",
                                                    "detect-v1.1",
                                                    "detect-v1.2",
                                                    "detect-v1.3",
                                                    "detect-v1.4"
                                                ]
                                            },
                                            "fast": {
                                                "type": "boolean",
                                                "default": true,
                                                "description": "Use the model's fast tier where it has one (Luna: about a third faster, twice the model cost; Haiku: no difference). False for the standard price."
                                            },
                                            "fresh": {
                                                "type": "boolean",
                                                "description": "Run again even if the same version, options and text are cached."
                                            }
                                        },
                                        "additionalProperties": false
                                    },
                                    "async": {
                                        "type": "boolean",
                                        "description": "Answer 202 at once and run in the background."
                                    }
                                }
                            },
                            "example": {
                                "text": "In today's fast-paced world, it's worth noting that effective communication is more important than ever."
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "The finished run.",
                        "headers": {
                            "X-Free-Limit": {
                                "$ref": "#/components/headers/X-Free-Limit"
                            },
                            "X-Free-Remaining": {
                                "$ref": "#/components/headers/X-Free-Remaining"
                            },
                            "X-Free-Reset": {
                                "$ref": "#/components/headers/X-Free-Reset"
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/DetectRun"
                                },
                                "example": {
                                    "id": "01JD7Y3W9K2M4P6Q8R0S2T4V6X",
                                    "skill": "detect",
                                    "status": "succeeded",
                                    "output": {
                                        "version": "detect-v1.1",
                                        "ai": 0.94,
                                        "label": "ai",
                                        "verdict": "Polished, evenly structured prose with stock phrasing and a tidy concluding line; most likely model-written.",
                                        "confidence": {
                                            "level": "high",
                                            "reason": "Several independent tells, and the classifier agrees."
                                        },
                                        "breakdown": {
                                            "human": 0.02,
                                            "ai": 0.95,
                                            "ai_edited": 0.02,
                                            "humanized": 0.01
                                        },
                                        "sentences": [
                                            {
                                                "text": "In today's fast-paced world, it's worth noting that effective communication is more important than ever.",
                                                "why": "Stock opener and filler phrase; says nothing specific."
                                            }
                                        ],
                                        "examples": [
                                            {
                                                "sentence": "In today's fast-paced world, it's worth noting that effective communication is more important than ever.",
                                                "points": 6,
                                                "rules": [
                                                    {
                                                        "rule": "ai-filler",
                                                        "name": "AI filler words and phrases",
                                                        "match": "in today's fast-paced world"
                                                    }
                                                ]
                                            }
                                        ],
                                        "tells": [
                                            {
                                                "rule": "ai-filler",
                                                "name": "AI filler words and phrases",
                                                "count": 2,
                                                "points": 6,
                                                "examples": [
                                                    "in today's fast-paced world",
                                                    "it's worth noting"
                                                ]
                                            }
                                        ],
                                        "agent": {
                                            "family": "unknown",
                                            "why": "Too short to tell model families apart."
                                        },
                                        "checks": {
                                            "linter": {
                                                "\u2026": "\u2026"
                                            },
                                            "tropa-mini": {
                                                "\u2026": "\u2026"
                                            },
                                            "judge": {
                                                "\u2026": "\u2026"
                                            }
                                        }
                                    },
                                    "charged_usd": "0.002600",
                                    "cached": false,
                                    "error": null,
                                    "created_at": "2026-10-19T14:00:00+00:00"
                                }
                            }
                        }
                    },
                    "202": {
                        "description": "Queued: poll `poll` (GET /runs/{id}) until `status` is `succeeded` or `failed`.",
                        "headers": {
                            "X-Free-Limit": {
                                "$ref": "#/components/headers/X-Free-Limit"
                            },
                            "X-Free-Remaining": {
                                "$ref": "#/components/headers/X-Free-Remaining"
                            },
                            "X-Free-Reset": {
                                "$ref": "#/components/headers/X-Free-Reset"
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/QueuedRun"
                                }
                            }
                        }
                    },
                    "402": {
                        "description": "Not enough credit (`insufficient_credit`). Nothing ran.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "422": {
                        "description": "Bad input (`invalid_request`) or the skill refused it (`skill_error`), e.g. an unknown version.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "502": {
                        "description": "An upstream model failed (`upstream_error`). Not charged.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "504": {
                        "description": "The text took longer than 85 s to process (`too_long`); send a shorter text. Not charged.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "$ref": "#/components/responses/FreeLimit"
                    }
                },
                "parameters": [
                    {
                        "$ref": "#/components/parameters/X-P3N-Client"
                    }
                ],
                "tags": [
                    "Skills"
                ],
                "security": [
                    {
                        "apiKey": []
                    },
                    {
                        "__PHP_Incomplete_Class_Name": "stdClass"
                    }
                ]
            }
        },
        "/editorial": {
            "post": {
                "operationId": "skills.editorial",
                "summary": "Editorial",
                "description": "Edits AI-assisted writing until it reads like a person wrote it.\n\nRuns in the background (202) when `async` is true or the text is over 20,000 characters. Details: https://p3n.si/skills/editorial",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "required": [
                                    "text"
                                ],
                                "properties": {
                                    "text": {
                                        "type": "string",
                                        "minLength": 1,
                                        "maxLength": 200000
                                    },
                                    "options": {
                                        "type": "object",
                                        "properties": {
                                            "brief": {
                                                "type": "string",
                                                "maxLength": 1000,
                                                "description": "Who reads this and what for. The editor judges the text against it."
                                            },
                                            "model": {
                                                "type": "string",
                                                "enum": [
                                                    "haiku",
                                                    "luna"
                                                ],
                                                "default": "haiku",
                                                "description": "The model that edits (AI detection uses its default)."
                                            },
                                            "version": {
                                                "type": "string",
                                                "description": "Pin a published editorial version for reproducible results. Default: the latest.",
                                                "enum": [
                                                    "editorial-v1",
                                                    "editorial-v1.1",
                                                    "editorial-v1.2",
                                                    "editorial-v1.3",
                                                    "editorial-v1.4"
                                                ]
                                            },
                                            "target_score": {
                                                "type": "integer",
                                                "minimum": 1,
                                                "maximum": 100,
                                                "default": 80,
                                                "description": "A session is done when the score reaches this."
                                            },
                                            "max_rounds": {
                                                "type": "integer",
                                                "minimum": 1,
                                                "maximum": 20,
                                                "default": 5,
                                                "description": "A session is done after this many rounds."
                                            },
                                            "detect": {
                                                "type": "string",
                                                "enum": [
                                                    "done",
                                                    "every",
                                                    "off"
                                                ],
                                                "default": "done",
                                                "description": "When AI detection runs on the text a round sends (`output.ai`): `done`, only on the round that ends the session; `every` round (adds 10-30 s and its cost to each); `off`."
                                            },
                                            "fast": {
                                                "type": "boolean",
                                                "default": true,
                                                "description": "Use the model's fast tier where it has one (Luna: about a third faster, twice the model cost; Haiku: no difference). False for the standard price."
                                            },
                                            "fresh": {
                                                "type": "boolean",
                                                "description": "Run again even if the same version, options and text are cached."
                                            }
                                        },
                                        "additionalProperties": false
                                    },
                                    "async": {
                                        "type": "boolean",
                                        "description": "Answer 202 at once and run in the background."
                                    }
                                }
                            },
                            "example": {
                                "text": "In today's fast-paced world, it's worth noting that effective communication is more important than ever."
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "The finished run.",
                        "headers": {
                            "X-Free-Limit": {
                                "$ref": "#/components/headers/X-Free-Limit"
                            },
                            "X-Free-Remaining": {
                                "$ref": "#/components/headers/X-Free-Remaining"
                            },
                            "X-Free-Reset": {
                                "$ref": "#/components/headers/X-Free-Reset"
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/EditorialRun"
                                },
                                "example": {
                                    "id": "01JD7Y3W9K2M4P6Q8R0S2T4V6X",
                                    "skill": "editorial",
                                    "status": "succeeded",
                                    "output": {
                                        "version": "editorial-v1",
                                        "model": "haiku",
                                        "round": 1,
                                        "score": 30,
                                        "summary": "The opener says nothing the reader can use; the claim needs a who and a how.",
                                        "progress": "",
                                        "items": [
                                            {
                                                "label": "P1S1",
                                                "type": "question",
                                                "original": "In today's fast-paced world, it's worth noting that effective communication is more important than ever.",
                                                "proposal": "",
                                                "question": "More important for whom, and what goes wrong without it?",
                                                "why": "A claim with no subject or consequence."
                                            }
                                        ],
                                        "revised": "In today's fast-paced world, it's worth noting that effective communication is more important than ever.",
                                        "done": false,
                                        "done_reason": null,
                                        "labelled": "P1S1 In today's fast-paced world, it's worth noting that effective communication is more important than ever.\n",
                                        "ai": null
                                    },
                                    "charged_usd": "0.002600",
                                    "cached": false,
                                    "error": null,
                                    "created_at": "2026-10-19T14:00:00+00:00"
                                }
                            }
                        }
                    },
                    "202": {
                        "description": "Queued: poll `poll` (GET /runs/{id}) until `status` is `succeeded` or `failed`.",
                        "headers": {
                            "X-Free-Limit": {
                                "$ref": "#/components/headers/X-Free-Limit"
                            },
                            "X-Free-Remaining": {
                                "$ref": "#/components/headers/X-Free-Remaining"
                            },
                            "X-Free-Reset": {
                                "$ref": "#/components/headers/X-Free-Reset"
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/QueuedRun"
                                }
                            }
                        }
                    },
                    "402": {
                        "description": "Not enough credit (`insufficient_credit`). Nothing ran.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "422": {
                        "description": "Bad input (`invalid_request`) or the skill refused it (`skill_error`), e.g. an unknown version.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "502": {
                        "description": "An upstream model failed (`upstream_error`). Not charged.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "504": {
                        "description": "The text took longer than 85 s to process (`too_long`); send a shorter text. Not charged.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "$ref": "#/components/responses/FreeLimit"
                    }
                },
                "parameters": [
                    {
                        "$ref": "#/components/parameters/X-P3N-Client"
                    }
                ],
                "tags": [
                    "Skills"
                ],
                "security": [
                    {
                        "apiKey": []
                    },
                    {
                        "__PHP_Incomplete_Class_Name": "stdClass"
                    }
                ]
            }
        },
        "/deslop": {
            "post": {
                "operationId": "skills.deslop",
                "summary": "Deslop",
                "description": "Cuts the filler so your text says what you mean.\n\nRuns in the background (202) when `async` is true or the text is over 20,000 characters. Details: https://p3n.si/skills/deslop",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "required": [
                                    "text"
                                ],
                                "properties": {
                                    "text": {
                                        "type": "string",
                                        "minLength": 1,
                                        "maxLength": 200000
                                    },
                                    "options": {
                                        "type": "object",
                                        "properties": {
                                            "brief": {
                                                "type": "string",
                                                "maxLength": 1000,
                                                "description": "Who reads this and what for. The editor judges the text against it."
                                            },
                                            "model": {
                                                "type": "string",
                                                "enum": [
                                                    "haiku",
                                                    "luna"
                                                ],
                                                "default": "haiku",
                                                "description": "The model that edits."
                                            },
                                            "version": {
                                                "type": "string",
                                                "description": "Pin a published deslop version for reproducible results. Default: the latest.",
                                                "enum": [
                                                    "deslop-v1",
                                                    "deslop-v1.1",
                                                    "deslop-v1.2",
                                                    "deslop-v1.3",
                                                    "deslop-v1.4",
                                                    "deslop-v1.5",
                                                    "deslop-v1.6"
                                                ]
                                            },
                                            "target_score": {
                                                "type": "integer",
                                                "minimum": 1,
                                                "maximum": 100,
                                                "default": 80,
                                                "description": "A session is done when the score reaches this."
                                            },
                                            "max_rounds": {
                                                "type": "integer",
                                                "minimum": 1,
                                                "maximum": 20,
                                                "default": 5,
                                                "description": "A session is done after this many rounds."
                                            },
                                            "fast": {
                                                "type": "boolean",
                                                "default": true,
                                                "description": "Use the model's fast tier where it has one (Luna: about a third faster, twice the model cost; Haiku: no difference). False for the standard price."
                                            },
                                            "fresh": {
                                                "type": "boolean",
                                                "description": "Run again even if the same version, options and text are cached."
                                            }
                                        },
                                        "additionalProperties": false
                                    },
                                    "async": {
                                        "type": "boolean",
                                        "description": "Answer 202 at once and run in the background."
                                    }
                                }
                            },
                            "example": {
                                "text": "In today's fast-paced world, it's worth noting that effective communication is more important than ever."
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "The finished run.",
                        "headers": {
                            "X-Free-Limit": {
                                "$ref": "#/components/headers/X-Free-Limit"
                            },
                            "X-Free-Remaining": {
                                "$ref": "#/components/headers/X-Free-Remaining"
                            },
                            "X-Free-Reset": {
                                "$ref": "#/components/headers/X-Free-Reset"
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/DeslopRun"
                                },
                                "example": {
                                    "id": "01JD7Y3W9K2M4P6Q8R0S2T4V6X",
                                    "skill": "deslop",
                                    "status": "succeeded",
                                    "output": {
                                        "version": "deslop-v1.2",
                                        "model": "haiku",
                                        "round": 1,
                                        "score": 35,
                                        "summary": "The opener says nothing the reader can use; the claim needs a who and a how.",
                                        "progress": "",
                                        "items": [
                                            {
                                                "label": "P1S1",
                                                "type": "question",
                                                "original": "In today's fast-paced world, it's worth noting that effective communication is more important than ever.",
                                                "proposal": "",
                                                "question": "More important for whom, and what goes wrong without it?",
                                                "why": "A claim with no subject or consequence."
                                            }
                                        ],
                                        "revised": "In today's fast-paced world, it's worth noting that effective communication is more important than ever.",
                                        "done": false,
                                        "done_reason": null,
                                        "labelled": "P1S1 In today's fast-paced world, it's worth noting that effective communication is more important than ever.\n"
                                    },
                                    "charged_usd": "0.002600",
                                    "cached": false,
                                    "error": null,
                                    "created_at": "2026-10-19T14:00:00+00:00"
                                }
                            }
                        }
                    },
                    "202": {
                        "description": "Queued: poll `poll` (GET /runs/{id}) until `status` is `succeeded` or `failed`.",
                        "headers": {
                            "X-Free-Limit": {
                                "$ref": "#/components/headers/X-Free-Limit"
                            },
                            "X-Free-Remaining": {
                                "$ref": "#/components/headers/X-Free-Remaining"
                            },
                            "X-Free-Reset": {
                                "$ref": "#/components/headers/X-Free-Reset"
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/QueuedRun"
                                }
                            }
                        }
                    },
                    "402": {
                        "description": "Not enough credit (`insufficient_credit`). Nothing ran.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "422": {
                        "description": "Bad input (`invalid_request`) or the skill refused it (`skill_error`), e.g. an unknown version.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "502": {
                        "description": "An upstream model failed (`upstream_error`). Not charged.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "504": {
                        "description": "The text took longer than 85 s to process (`too_long`); send a shorter text. Not charged.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "$ref": "#/components/responses/FreeLimit"
                    }
                },
                "parameters": [
                    {
                        "$ref": "#/components/parameters/X-P3N-Client"
                    }
                ],
                "tags": [
                    "Skills"
                ],
                "security": [
                    {
                        "apiKey": []
                    },
                    {
                        "__PHP_Incomplete_Class_Name": "stdClass"
                    }
                ]
            }
        },
        "/humanize": {
            "post": {
                "operationId": "skills.humanize",
                "summary": "Humanize",
                "description": "Rewrites text so it stops sounding like AI.\n\nRuns in the background (202) when `async` is true or the text is over 20,000 characters. Details: https://p3n.si/skills/humanize",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "required": [
                                    "text"
                                ],
                                "properties": {
                                    "text": {
                                        "type": "string",
                                        "minLength": 1,
                                        "maxLength": 200000
                                    },
                                    "options": {
                                        "type": "object",
                                        "properties": {
                                            "model": {
                                                "type": "string",
                                                "enum": [
                                                    "haiku",
                                                    "luna"
                                                ],
                                                "default": "haiku",
                                                "description": "The model that rewrites."
                                            },
                                            "version": {
                                                "type": "string",
                                                "description": "Pin a published humanize version for reproducible results. Default: the latest.",
                                                "enum": [
                                                    "humanize-v1",
                                                    "humanize-v1.1",
                                                    "humanize-v1.2",
                                                    "humanize-v1.3",
                                                    "humanize-v1.4"
                                                ]
                                            },
                                            "before": {
                                                "type": "boolean",
                                                "default": true,
                                                "description": "Also score the text as sent (`ai_before`)."
                                            },
                                            "fast": {
                                                "type": "boolean",
                                                "default": true,
                                                "description": "Use the model's fast tier where it has one (Luna: about a third faster, twice the model cost; Haiku: no difference). False for the standard price."
                                            },
                                            "fresh": {
                                                "type": "boolean",
                                                "description": "Run again even if the same version, options and text are cached."
                                            }
                                        },
                                        "additionalProperties": false
                                    },
                                    "async": {
                                        "type": "boolean",
                                        "description": "Answer 202 at once and run in the background."
                                    }
                                }
                            },
                            "example": {
                                "text": "In today's fast-paced world, it's worth noting that effective communication is more important than ever."
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "The finished run.",
                        "headers": {
                            "X-Free-Limit": {
                                "$ref": "#/components/headers/X-Free-Limit"
                            },
                            "X-Free-Remaining": {
                                "$ref": "#/components/headers/X-Free-Remaining"
                            },
                            "X-Free-Reset": {
                                "$ref": "#/components/headers/X-Free-Reset"
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/HumanizeRun"
                                },
                                "example": {
                                    "id": "01JD7Y3W9K2M4P6Q8R0S2T4V6X",
                                    "skill": "humanize",
                                    "status": "succeeded",
                                    "output": {
                                        "version": "humanize-v1",
                                        "model": "haiku",
                                        "text": "Clear communication matters more now. Why? Most of the team works remotely.",
                                        "ai_before": 0.99,
                                        "ai_after": 0.04,
                                        "label_after": "human",
                                        "passes": true,
                                        "candidates": 3,
                                        "invented_blocked": []
                                    },
                                    "charged_usd": "0.002600",
                                    "cached": false,
                                    "error": null,
                                    "created_at": "2026-10-19T14:00:00+00:00"
                                }
                            }
                        }
                    },
                    "202": {
                        "description": "Queued: poll `poll` (GET /runs/{id}) until `status` is `succeeded` or `failed`.",
                        "headers": {
                            "X-Free-Limit": {
                                "$ref": "#/components/headers/X-Free-Limit"
                            },
                            "X-Free-Remaining": {
                                "$ref": "#/components/headers/X-Free-Remaining"
                            },
                            "X-Free-Reset": {
                                "$ref": "#/components/headers/X-Free-Reset"
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/QueuedRun"
                                }
                            }
                        }
                    },
                    "402": {
                        "description": "Not enough credit (`insufficient_credit`). Nothing ran.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "422": {
                        "description": "Bad input (`invalid_request`) or the skill refused it (`skill_error`), e.g. an unknown version.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "502": {
                        "description": "An upstream model failed (`upstream_error`). Not charged.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "504": {
                        "description": "The text took longer than 85 s to process (`too_long`); send a shorter text. Not charged.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "$ref": "#/components/responses/FreeLimit"
                    }
                },
                "parameters": [
                    {
                        "$ref": "#/components/parameters/X-P3N-Client"
                    }
                ],
                "tags": [
                    "Skills"
                ],
                "security": [
                    {
                        "apiKey": []
                    },
                    {
                        "__PHP_Incomplete_Class_Name": "stdClass"
                    }
                ]
            }
        },
        "/editorial/sessions": {
            "post": {
                "operationId": "editorial.session.store",
                "description": "Send the text, with options for the whole session: brief, model, version, target_score, max_rounds, and for\neditorial detect (done | every | off).\nThe answer holds the session and the first round.",
                "summary": "Start a editorial session",
                "tags": [
                    "Editorial sessions"
                ],
                "parameters": [
                    {
                        "$ref": "#/components/parameters/X-P3N-Client"
                    }
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "text": {
                                        "type": "string",
                                        "maxLength": 200000
                                    },
                                    "options": {
                                        "type": "object",
                                        "properties": {
                                            "brief": {
                                                "type": "string",
                                                "maxLength": 1000,
                                                "description": "Who reads this and what for. The editor judges the text against it."
                                            },
                                            "model": {
                                                "type": "string",
                                                "enum": [
                                                    "haiku",
                                                    "luna"
                                                ],
                                                "default": "haiku",
                                                "description": "The model that edits (AI detection uses its default)."
                                            },
                                            "version": {
                                                "type": "string",
                                                "description": "Pin a published editorial version for reproducible results. Default: the latest.",
                                                "enum": [
                                                    "editorial-v1",
                                                    "editorial-v1.1",
                                                    "editorial-v1.2",
                                                    "editorial-v1.3",
                                                    "editorial-v1.4"
                                                ]
                                            },
                                            "target_score": {
                                                "type": "integer",
                                                "minimum": 1,
                                                "maximum": 100,
                                                "default": 80,
                                                "description": "A session is done when the score reaches this."
                                            },
                                            "max_rounds": {
                                                "type": "integer",
                                                "minimum": 1,
                                                "maximum": 20,
                                                "default": 5,
                                                "description": "A session is done after this many rounds."
                                            },
                                            "detect": {
                                                "type": "string",
                                                "enum": [
                                                    "done",
                                                    "every",
                                                    "off"
                                                ],
                                                "default": "done",
                                                "description": "When AI detection runs on the text a round sends (`output.ai`): `done`, only on the round that ends the session; `every` round (adds 10-30 s and its cost to each); `off`."
                                            },
                                            "fast": {
                                                "type": "boolean",
                                                "default": true,
                                                "description": "Use the model's fast tier where it has one (Luna: about a third faster, twice the model cost; Haiku: no difference). False for the standard price."
                                            }
                                        },
                                        "additionalProperties": false
                                    }
                                },
                                "required": [
                                    "text"
                                ]
                            },
                            "example": {
                                "text": "In today's fast-paced world, it's worth noting that effective communication is more important than ever.",
                                "options": {
                                    "brief": "new hires on the support team, learning the escalation rules"
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "201": {
                        "description": "",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "session": {
                                            "type": "array",
                                            "items": {
                                                "__PHP_Incomplete_Class_Name": "stdClass"
                                            }
                                        },
                                        "run": {
                                            "$ref": "#/components/schemas/EditorialRun"
                                        }
                                    },
                                    "required": [
                                        "session",
                                        "run"
                                    ]
                                }
                            }
                        }
                    },
                    "422": {
                        "$ref": "#/components/responses/ValidationException"
                    },
                    "429": {
                        "$ref": "#/components/responses/FreeLimit"
                    }
                },
                "security": [
                    {
                        "apiKey": []
                    },
                    {
                        "__PHP_Incomplete_Class_Name": "stdClass"
                    }
                ]
            }
        },
        "/deslop/sessions": {
            "post": {
                "operationId": "deslop.session.store",
                "description": "Send the text, with options for the whole session: brief, model, version, target_score, max_rounds, and for\neditorial detect (done | every | off).\nThe answer holds the session and the first round.",
                "summary": "Start a deslop session",
                "tags": [
                    "Deslop sessions"
                ],
                "parameters": [
                    {
                        "$ref": "#/components/parameters/X-P3N-Client"
                    }
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "text": {
                                        "type": "string",
                                        "maxLength": 200000
                                    },
                                    "options": {
                                        "type": "object",
                                        "properties": {
                                            "brief": {
                                                "type": "string",
                                                "maxLength": 1000,
                                                "description": "Who reads this and what for. The editor judges the text against it."
                                            },
                                            "model": {
                                                "type": "string",
                                                "enum": [
                                                    "haiku",
                                                    "luna"
                                                ],
                                                "default": "haiku",
                                                "description": "The model that edits."
                                            },
                                            "version": {
                                                "type": "string",
                                                "description": "Pin a published deslop version for reproducible results. Default: the latest.",
                                                "enum": [
                                                    "deslop-v1",
                                                    "deslop-v1.1",
                                                    "deslop-v1.2",
                                                    "deslop-v1.3",
                                                    "deslop-v1.4",
                                                    "deslop-v1.5",
                                                    "deslop-v1.6"
                                                ]
                                            },
                                            "target_score": {
                                                "type": "integer",
                                                "minimum": 1,
                                                "maximum": 100,
                                                "default": 80,
                                                "description": "A session is done when the score reaches this."
                                            },
                                            "max_rounds": {
                                                "type": "integer",
                                                "minimum": 1,
                                                "maximum": 20,
                                                "default": 5,
                                                "description": "A session is done after this many rounds."
                                            },
                                            "fast": {
                                                "type": "boolean",
                                                "default": true,
                                                "description": "Use the model's fast tier where it has one (Luna: about a third faster, twice the model cost; Haiku: no difference). False for the standard price."
                                            }
                                        },
                                        "additionalProperties": false
                                    }
                                },
                                "required": [
                                    "text"
                                ]
                            },
                            "example": {
                                "text": "In today's fast-paced world, it's worth noting that effective communication is more important than ever.",
                                "options": {
                                    "brief": "new hires on the support team, learning the escalation rules"
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "201": {
                        "description": "",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "session": {
                                            "type": "array",
                                            "items": {
                                                "__PHP_Incomplete_Class_Name": "stdClass"
                                            }
                                        },
                                        "run": {
                                            "$ref": "#/components/schemas/DeslopRun"
                                        }
                                    },
                                    "required": [
                                        "session",
                                        "run"
                                    ]
                                }
                            }
                        }
                    },
                    "422": {
                        "$ref": "#/components/responses/ValidationException"
                    },
                    "429": {
                        "$ref": "#/components/responses/FreeLimit"
                    }
                },
                "security": [
                    {
                        "apiKey": []
                    },
                    {
                        "__PHP_Incomplete_Class_Name": "stdClass"
                    }
                ]
            }
        },
        "/editorial/sessions/{session}": {
            "get": {
                "operationId": "editorial.session.show",
                "description": "The session with every message so far.",
                "summary": "Get a session",
                "tags": [
                    "Editorial sessions"
                ],
                "parameters": [
                    {
                        "name": "session",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "string"
                        }
                    },
                    {
                        "$ref": "#/components/parameters/X-P3N-Client"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "array",
                                    "items": {
                                        "__PHP_Incomplete_Class_Name": "stdClass"
                                    }
                                }
                            }
                        }
                    },
                    "429": {
                        "$ref": "#/components/responses/FreeLimit"
                    }
                },
                "security": [
                    {
                        "apiKey": []
                    },
                    {
                        "__PHP_Incomplete_Class_Name": "stdClass"
                    }
                ]
            }
        },
        "/deslop/sessions/{session}": {
            "get": {
                "operationId": "deslop.session.show",
                "description": "The session with every message so far.",
                "summary": "Get a session",
                "tags": [
                    "Deslop sessions"
                ],
                "parameters": [
                    {
                        "name": "session",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "string"
                        }
                    },
                    {
                        "$ref": "#/components/parameters/X-P3N-Client"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "array",
                                    "items": {
                                        "__PHP_Incomplete_Class_Name": "stdClass"
                                    }
                                }
                            }
                        }
                    },
                    "429": {
                        "$ref": "#/components/responses/FreeLimit"
                    }
                },
                "security": [
                    {
                        "apiKey": []
                    },
                    {
                        "__PHP_Incomplete_Class_Name": "stdClass"
                    }
                ]
            }
        },
        "/editorial/sessions/{session}/messages": {
            "post": {
                "operationId": "editorial.session.message",
                "description": "The revised text, whole, with your answers to the editor's questions. 410 once the session has expired.",
                "summary": "Send the next round",
                "tags": [
                    "Editorial sessions"
                ],
                "parameters": [
                    {
                        "name": "session",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "string"
                        }
                    },
                    {
                        "$ref": "#/components/parameters/X-P3N-Client"
                    }
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "message": {
                                        "type": "string",
                                        "maxLength": 200000,
                                        "description": "The revised text, whole."
                                    },
                                    "answers": {
                                        "type": [
                                            "string",
                                            "null"
                                        ],
                                        "maxLength": 20000,
                                        "description": "Your answers to the editor's questions, by label (e.g. `P2S1: the lock file`)."
                                    }
                                },
                                "required": [
                                    "message"
                                ]
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "session": {
                                            "type": "array",
                                            "items": {
                                                "__PHP_Incomplete_Class_Name": "stdClass"
                                            }
                                        },
                                        "run": {
                                            "$ref": "#/components/schemas/EditorialRun"
                                        }
                                    },
                                    "required": [
                                        "session",
                                        "run"
                                    ]
                                }
                            }
                        }
                    },
                    "410": {
                        "description": "An error",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "message": {
                                            "type": "string",
                                            "description": "Error overview.",
                                            "examples": [
                                                "Session expired. Start a new one."
                                            ]
                                        }
                                    },
                                    "required": [
                                        "message"
                                    ]
                                }
                            }
                        }
                    },
                    "422": {
                        "$ref": "#/components/responses/ValidationException"
                    },
                    "429": {
                        "$ref": "#/components/responses/FreeLimit"
                    }
                },
                "security": [
                    {
                        "apiKey": []
                    },
                    {
                        "__PHP_Incomplete_Class_Name": "stdClass"
                    }
                ]
            }
        },
        "/deslop/sessions/{session}/messages": {
            "post": {
                "operationId": "deslop.session.message",
                "description": "The revised text, whole, with your answers to the editor's questions. 410 once the session has expired.",
                "summary": "Send the next round",
                "tags": [
                    "Deslop sessions"
                ],
                "parameters": [
                    {
                        "name": "session",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "string"
                        }
                    },
                    {
                        "$ref": "#/components/parameters/X-P3N-Client"
                    }
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "message": {
                                        "type": "string",
                                        "maxLength": 200000,
                                        "description": "The revised text, whole."
                                    },
                                    "answers": {
                                        "type": [
                                            "string",
                                            "null"
                                        ],
                                        "maxLength": 20000,
                                        "description": "Your answers to the editor's questions, by label (e.g. `P2S1: the lock file`)."
                                    }
                                },
                                "required": [
                                    "message"
                                ]
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "session": {
                                            "type": "array",
                                            "items": {
                                                "__PHP_Incomplete_Class_Name": "stdClass"
                                            }
                                        },
                                        "run": {
                                            "$ref": "#/components/schemas/DeslopRun"
                                        }
                                    },
                                    "required": [
                                        "session",
                                        "run"
                                    ]
                                }
                            }
                        }
                    },
                    "410": {
                        "description": "An error",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "message": {
                                            "type": "string",
                                            "description": "Error overview.",
                                            "examples": [
                                                "Session expired. Start a new one."
                                            ]
                                        }
                                    },
                                    "required": [
                                        "message"
                                    ]
                                }
                            }
                        }
                    },
                    "422": {
                        "$ref": "#/components/responses/ValidationException"
                    },
                    "429": {
                        "$ref": "#/components/responses/FreeLimit"
                    }
                },
                "security": [
                    {
                        "apiKey": []
                    },
                    {
                        "__PHP_Incomplete_Class_Name": "stdClass"
                    }
                ]
            }
        },
        "/editorial/sessions/{session}/author": {
            "post": {
                "operationId": "editorial.session.author",
                "description": "Deslop and editorial: a model standing in for the author reads the editor's last round and returns `text` (the revised text)\nand `answers` (one line per question; facts it had to pick end in \"(assumed)\"). Nothing is sent to the editor:\nsend them as the next message, edited or not. Billed like a skill run. For trying the loop without writing\nthe answers yourself. The run's `skill` is `author`.",
                "summary": "Answer for me (stand-in author)",
                "tags": [
                    "Editorial sessions"
                ],
                "parameters": [
                    {
                        "name": "session",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "string"
                        }
                    },
                    {
                        "$ref": "#/components/parameters/X-P3N-Client"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "id": {
                                            "type": "string"
                                        },
                                        "skill": {
                                            "type": "string"
                                        },
                                        "status": {
                                            "type": "string"
                                        },
                                        "output": {
                                            "type": [
                                                "array",
                                                "null"
                                            ],
                                            "items": {
                                                "__PHP_Incomplete_Class_Name": "stdClass"
                                            }
                                        },
                                        "charged_usd": {
                                            "type": "string"
                                        },
                                        "cached": {
                                            "type": "boolean"
                                        },
                                        "error": {
                                            "type": [
                                                "string",
                                                "null"
                                            ]
                                        },
                                        "created_at": {
                                            "type": [
                                                "string",
                                                "null"
                                            ]
                                        }
                                    },
                                    "required": [
                                        "id",
                                        "skill",
                                        "status",
                                        "output",
                                        "charged_usd",
                                        "cached",
                                        "error",
                                        "created_at"
                                    ]
                                }
                            }
                        }
                    },
                    "429": {
                        "$ref": "#/components/responses/FreeLimit"
                    }
                },
                "security": [
                    {
                        "apiKey": []
                    },
                    {
                        "__PHP_Incomplete_Class_Name": "stdClass"
                    }
                ]
            }
        },
        "/deslop/sessions/{session}/author": {
            "post": {
                "operationId": "deslop.session.author",
                "description": "Deslop and editorial: a model standing in for the author reads the editor's last round and returns `text` (the revised text)\nand `answers` (one line per question; facts it had to pick end in \"(assumed)\"). Nothing is sent to the editor:\nsend them as the next message, edited or not. Billed like a skill run. For trying the loop without writing\nthe answers yourself. The run's `skill` is `author`.",
                "summary": "Answer for me (stand-in author)",
                "tags": [
                    "Deslop sessions"
                ],
                "parameters": [
                    {
                        "name": "session",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "string"
                        }
                    },
                    {
                        "$ref": "#/components/parameters/X-P3N-Client"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "id": {
                                            "type": "string"
                                        },
                                        "skill": {
                                            "type": "string"
                                        },
                                        "status": {
                                            "type": "string"
                                        },
                                        "output": {
                                            "type": [
                                                "array",
                                                "null"
                                            ],
                                            "items": {
                                                "__PHP_Incomplete_Class_Name": "stdClass"
                                            }
                                        },
                                        "charged_usd": {
                                            "type": "string"
                                        },
                                        "cached": {
                                            "type": "boolean"
                                        },
                                        "error": {
                                            "type": [
                                                "string",
                                                "null"
                                            ]
                                        },
                                        "created_at": {
                                            "type": [
                                                "string",
                                                "null"
                                            ]
                                        }
                                    },
                                    "required": [
                                        "id",
                                        "skill",
                                        "status",
                                        "output",
                                        "charged_usd",
                                        "cached",
                                        "error",
                                        "created_at"
                                    ]
                                }
                            }
                        }
                    },
                    "429": {
                        "$ref": "#/components/responses/FreeLimit"
                    }
                },
                "security": [
                    {
                        "apiKey": []
                    },
                    {
                        "__PHP_Incomplete_Class_Name": "stdClass"
                    }
                ]
            }
        },
        "/editorial/sessions/{session}/writer": {
            "post": {
                "operationId": "editorial.session.writer",
                "description": "The same as `/author`, under its original name; kept so existing callers keep working (D38). The run's `skill`\nis `writer`, as it always was.",
                "summary": "Answer for me (original path)",
                "tags": [
                    "Editorial sessions"
                ],
                "parameters": [
                    {
                        "name": "session",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "string"
                        }
                    },
                    {
                        "$ref": "#/components/parameters/X-P3N-Client"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "array",
                                    "items": {
                                        "__PHP_Incomplete_Class_Name": "stdClass"
                                    }
                                }
                            }
                        }
                    },
                    "429": {
                        "$ref": "#/components/responses/FreeLimit"
                    }
                },
                "security": [
                    {
                        "apiKey": []
                    },
                    {
                        "__PHP_Incomplete_Class_Name": "stdClass"
                    }
                ]
            }
        },
        "/deslop/sessions/{session}/writer": {
            "post": {
                "operationId": "deslop.session.writer",
                "description": "The same as `/author`, under its original name; kept so existing callers keep working (D38). The run's `skill`\nis `writer`, as it always was.",
                "summary": "Answer for me (original path)",
                "tags": [
                    "Deslop sessions"
                ],
                "parameters": [
                    {
                        "name": "session",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "string"
                        }
                    },
                    {
                        "$ref": "#/components/parameters/X-P3N-Client"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "array",
                                    "items": {
                                        "__PHP_Incomplete_Class_Name": "stdClass"
                                    }
                                }
                            }
                        }
                    },
                    "429": {
                        "$ref": "#/components/responses/FreeLimit"
                    }
                },
                "security": [
                    {
                        "apiKey": []
                    },
                    {
                        "__PHP_Incomplete_Class_Name": "stdClass"
                    }
                ]
            }
        }
    },
    "components": {
        "responses": {
            "ModelNotFoundException": {
                "description": "Not found",
                "content": {
                    "application/json": {
                        "schema": {
                            "type": "object",
                            "properties": {
                                "message": {
                                    "type": "string",
                                    "description": "Error overview."
                                }
                            },
                            "required": [
                                "message"
                            ]
                        }
                    }
                }
            },
            "ValidationException": {
                "description": "Validation error",
                "content": {
                    "application/json": {
                        "schema": {
                            "type": "object",
                            "properties": {
                                "message": {
                                    "type": "string",
                                    "description": "Errors overview."
                                },
                                "errors": {
                                    "type": "object",
                                    "description": "A detailed description of each field that failed validation.",
                                    "additionalProperties": {
                                        "type": "array",
                                        "items": {
                                            "type": "string"
                                        }
                                    }
                                }
                            },
                            "required": [
                                "message",
                                "errors"
                            ]
                        }
                    }
                }
            },
            "FreeLimit": {
                "description": "Keyless allowance used up for this hour (`free_limit`), or too many requests with a key (`rate_limited`).",
                "content": {
                    "application/json": {
                        "schema": {
                            "$ref": "#/components/schemas/Error"
                        }
                    }
                },
                "headers": {
                    "Retry-After": {
                        "schema": {
                            "type": "integer"
                        },
                        "description": "Seconds until you can call again."
                    }
                }
            }
        },
        "securitySchemes": {
            "apiKey": {
                "type": "http",
                "scheme": "bearer",
                "bearerFormat": "p3n_...",
                "description": "An API key from the dashboard. Optional: without it, up to 10 calls an hour per IP are free."
            }
        },
        "schemas": {
            "Run": {
                "type": "object",
                "required": [
                    "id",
                    "skill",
                    "status",
                    "output",
                    "charged_usd",
                    "cached",
                    "error",
                    "created_at"
                ],
                "properties": {
                    "id": {
                        "type": "string",
                        "description": "Run id (ULID)."
                    },
                    "skill": {
                        "type": "string"
                    },
                    "status": {
                        "type": "string",
                        "enum": [
                            "queued",
                            "running",
                            "succeeded",
                            "failed"
                        ]
                    },
                    "output": {
                        "oneOf": [
                            {
                                "$ref": "#/components/schemas/DetectOutput"
                            },
                            {
                                "$ref": "#/components/schemas/TextOutput"
                            },
                            {
                                "$ref": "#/components/schemas/EditorialOutput"
                            },
                            {
                                "$ref": "#/components/schemas/DeslopOutput"
                            },
                            {
                                "$ref": "#/components/schemas/HumanizeOutput"
                            },
                            {
                                "type": "null"
                            }
                        ],
                        "description": "Null until the run has succeeded."
                    },
                    "charged_usd": {
                        "type": "string",
                        "description": "What this call cost, in USD (6 decimals). Keyless calls: 0.",
                        "examples": [
                            "0.002600"
                        ]
                    },
                    "cached": {
                        "type": "boolean",
                        "description": "Served from cache: the same skill version, options and text ran before. Charged the base fee only."
                    },
                    "error": {
                        "type": [
                            "string",
                            "null"
                        ]
                    },
                    "created_at": {
                        "type": "string",
                        "format": "date-time"
                    }
                }
            },
            "DeslopRun": {
                "type": "object",
                "required": [
                    "id",
                    "skill",
                    "status",
                    "output",
                    "charged_usd",
                    "cached",
                    "error",
                    "created_at"
                ],
                "properties": {
                    "id": {
                        "type": "string",
                        "description": "Run id (ULID)."
                    },
                    "skill": {
                        "type": "string"
                    },
                    "status": {
                        "type": "string",
                        "enum": [
                            "queued",
                            "running",
                            "succeeded",
                            "failed"
                        ]
                    },
                    "output": {
                        "oneOf": [
                            {
                                "$ref": "#/components/schemas/DeslopOutput"
                            },
                            {
                                "type": "null"
                            }
                        ],
                        "description": "Null until the run has succeeded."
                    },
                    "charged_usd": {
                        "type": "string",
                        "description": "What this call cost, in USD (6 decimals). Keyless calls: 0.",
                        "examples": [
                            "0.002600"
                        ]
                    },
                    "cached": {
                        "type": "boolean",
                        "description": "Served from cache: the same skill version, options and text ran before. Charged the base fee only."
                    },
                    "error": {
                        "type": [
                            "string",
                            "null"
                        ]
                    },
                    "created_at": {
                        "type": "string",
                        "format": "date-time"
                    }
                }
            },
            "DetectRun": {
                "type": "object",
                "required": [
                    "id",
                    "skill",
                    "status",
                    "output",
                    "charged_usd",
                    "cached",
                    "error",
                    "created_at"
                ],
                "properties": {
                    "id": {
                        "type": "string",
                        "description": "Run id (ULID)."
                    },
                    "skill": {
                        "type": "string"
                    },
                    "status": {
                        "type": "string",
                        "enum": [
                            "queued",
                            "running",
                            "succeeded",
                            "failed"
                        ]
                    },
                    "output": {
                        "oneOf": [
                            {
                                "$ref": "#/components/schemas/DetectOutput"
                            },
                            {
                                "type": "null"
                            }
                        ],
                        "description": "Null until the run has succeeded."
                    },
                    "charged_usd": {
                        "type": "string",
                        "description": "What this call cost, in USD (6 decimals). Keyless calls: 0.",
                        "examples": [
                            "0.002600"
                        ]
                    },
                    "cached": {
                        "type": "boolean",
                        "description": "Served from cache: the same skill version, options and text ran before. Charged the base fee only."
                    },
                    "error": {
                        "type": [
                            "string",
                            "null"
                        ]
                    },
                    "created_at": {
                        "type": "string",
                        "format": "date-time"
                    }
                }
            },
            "TextRun": {
                "type": "object",
                "required": [
                    "id",
                    "skill",
                    "status",
                    "output",
                    "charged_usd",
                    "cached",
                    "error",
                    "created_at"
                ],
                "properties": {
                    "id": {
                        "type": "string",
                        "description": "Run id (ULID)."
                    },
                    "skill": {
                        "type": "string"
                    },
                    "status": {
                        "type": "string",
                        "enum": [
                            "queued",
                            "running",
                            "succeeded",
                            "failed"
                        ]
                    },
                    "output": {
                        "oneOf": [
                            {
                                "$ref": "#/components/schemas/TextOutput"
                            },
                            {
                                "type": "null"
                            }
                        ],
                        "description": "Null until the run has succeeded."
                    },
                    "charged_usd": {
                        "type": "string",
                        "description": "What this call cost, in USD (6 decimals). Keyless calls: 0.",
                        "examples": [
                            "0.002600"
                        ]
                    },
                    "cached": {
                        "type": "boolean",
                        "description": "Served from cache: the same skill version, options and text ran before. Charged the base fee only."
                    },
                    "error": {
                        "type": [
                            "string",
                            "null"
                        ]
                    },
                    "created_at": {
                        "type": "string",
                        "format": "date-time"
                    }
                }
            },
            "EditorialRun": {
                "type": "object",
                "required": [
                    "id",
                    "skill",
                    "status",
                    "output",
                    "charged_usd",
                    "cached",
                    "error",
                    "created_at"
                ],
                "properties": {
                    "id": {
                        "type": "string",
                        "description": "Run id (ULID)."
                    },
                    "skill": {
                        "type": "string"
                    },
                    "status": {
                        "type": "string",
                        "enum": [
                            "queued",
                            "running",
                            "succeeded",
                            "failed"
                        ]
                    },
                    "output": {
                        "oneOf": [
                            {
                                "$ref": "#/components/schemas/EditorialOutput"
                            },
                            {
                                "type": "null"
                            }
                        ],
                        "description": "Null until the run has succeeded."
                    },
                    "charged_usd": {
                        "type": "string",
                        "description": "What this call cost, in USD (6 decimals). Keyless calls: 0.",
                        "examples": [
                            "0.002600"
                        ]
                    },
                    "cached": {
                        "type": "boolean",
                        "description": "Served from cache: the same skill version, options and text ran before. Charged the base fee only."
                    },
                    "error": {
                        "type": [
                            "string",
                            "null"
                        ]
                    },
                    "created_at": {
                        "type": "string",
                        "format": "date-time"
                    }
                }
            },
            "HumanizeRun": {
                "type": "object",
                "required": [
                    "id",
                    "skill",
                    "status",
                    "output",
                    "charged_usd",
                    "cached",
                    "error",
                    "created_at"
                ],
                "properties": {
                    "id": {
                        "type": "string",
                        "description": "Run id (ULID)."
                    },
                    "skill": {
                        "type": "string"
                    },
                    "status": {
                        "type": "string",
                        "enum": [
                            "queued",
                            "running",
                            "succeeded",
                            "failed"
                        ]
                    },
                    "output": {
                        "oneOf": [
                            {
                                "$ref": "#/components/schemas/HumanizeOutput"
                            },
                            {
                                "type": "null"
                            }
                        ],
                        "description": "Null until the run has succeeded."
                    },
                    "charged_usd": {
                        "type": "string",
                        "description": "What this call cost, in USD (6 decimals). Keyless calls: 0.",
                        "examples": [
                            "0.002600"
                        ]
                    },
                    "cached": {
                        "type": "boolean",
                        "description": "Served from cache: the same skill version, options and text ran before. Charged the base fee only."
                    },
                    "error": {
                        "type": [
                            "string",
                            "null"
                        ]
                    },
                    "created_at": {
                        "type": "string",
                        "format": "date-time"
                    }
                }
            },
            "QueuedRun": {
                "allOf": [
                    {
                        "type": "object",
                        "required": [
                            "id",
                            "skill",
                            "status",
                            "output",
                            "charged_usd",
                            "cached",
                            "error",
                            "created_at"
                        ],
                        "properties": {
                            "id": {
                                "type": "string",
                                "description": "Run id (ULID)."
                            },
                            "skill": {
                                "type": "string"
                            },
                            "status": {
                                "type": "string",
                                "enum": [
                                    "queued",
                                    "running",
                                    "succeeded",
                                    "failed"
                                ]
                            },
                            "output": {
                                "type": "null",
                                "description": "Null until the run has succeeded."
                            },
                            "charged_usd": {
                                "type": "string",
                                "description": "What this call cost, in USD (6 decimals). Keyless calls: 0.",
                                "examples": [
                                    "0.002600"
                                ]
                            },
                            "cached": {
                                "type": "boolean",
                                "description": "Served from cache: the same skill version, options and text ran before. Charged the base fee only."
                            },
                            "error": {
                                "type": [
                                    "string",
                                    "null"
                                ]
                            },
                            "created_at": {
                                "type": "string",
                                "format": "date-time"
                            }
                        }
                    },
                    {
                        "type": "object",
                        "properties": {
                            "poll": {
                                "type": "string",
                                "format": "uri"
                            }
                        }
                    }
                ]
            },
            "HumanizeOutput": {
                "type": "object",
                "required": [
                    "version",
                    "text",
                    "ai_after",
                    "label_after",
                    "passes"
                ],
                "properties": {
                    "version": {
                        "type": "string",
                        "examples": [
                            "humanize-v1"
                        ]
                    },
                    "model": {
                        "type": "string",
                        "description": "The model that rewrote.",
                        "examples": [
                            "haiku"
                        ]
                    },
                    "text": {
                        "type": "string",
                        "description": "The rewritten text. Headings, lists, quotes and code are as sent."
                    },
                    "ai_before": {
                        "type": [
                            "number",
                            "null"
                        ],
                        "description": "p(ai) for the text as sent, from our AI classifier (one of AI Detection's checks, not its full score); null with `before: false`."
                    },
                    "ai_after": {
                        "type": "number",
                        "description": "p(ai) for the rewrite, from the same classifier."
                    },
                    "label_after": {
                        "type": "string",
                        "enum": [
                            "human",
                            "ai",
                            "ai_edited",
                            "humanized"
                        ],
                        "description": "The classifier's top label for the rewrite."
                    },
                    "passes": {
                        "type": "boolean",
                        "description": "The rewrite no longer reads as AI: its top label is anything but `ai`."
                    },
                    "candidates": {
                        "type": "integer",
                        "description": "Rewrites tried per paragraph; the one the classifier scored lowest is kept (1 for long texts)."
                    },
                    "invented_blocked": {
                        "type": "array",
                        "items": {
                            "type": "string"
                        },
                        "description": "Numbers and names a rewrite added that the text does not have; those paragraphs were kept as sent."
                    }
                }
            },
            "TextOutput": {
                "type": "object",
                "required": [
                    "text"
                ],
                "properties": {
                    "text": {
                        "type": "string",
                        "description": "The rewritten text."
                    }
                }
            },
            "DeslopOutput": {
                "type": "object",
                "required": [
                    "version",
                    "round",
                    "score",
                    "summary",
                    "items",
                    "revised"
                ],
                "properties": {
                    "version": {
                        "type": "string",
                        "examples": [
                            "deslop-v1.2"
                        ]
                    },
                    "round": {
                        "type": "integer",
                        "description": "Which round of the session this is; 1 for a one-off call."
                    },
                    "score": {
                        "type": "integer",
                        "minimum": 0,
                        "maximum": 100,
                        "description": "The editor's score for the text as sent: clear, accurate, complete for the brief."
                    },
                    "summary": {
                        "type": "string",
                        "description": "What holds the text back, in a few sentences."
                    },
                    "progress": {
                        "type": "string",
                        "description": "From round 2: what the revision fixed and what is still open. Empty on round 1."
                    },
                    "items": {
                        "type": "array",
                        "description": "One per sentence, sentence range or paragraph the editor would change or ask about, in text order.",
                        "items": {
                            "type": "object",
                            "required": [
                                "label",
                                "type"
                            ],
                            "properties": {
                                "label": {
                                    "type": "string",
                                    "description": "Where: P2S3 (paragraph 2, sentence 3), P2S3-S5, P2 (whole paragraph), H1 (heading), B1 (list item).",
                                    "examples": [
                                        "P2S3"
                                    ]
                                },
                                "type": {
                                    "type": "string",
                                    "enum": [
                                        "change",
                                        "question",
                                        "cut",
                                        "note"
                                    ]
                                },
                                "original": {
                                    "type": "string",
                                    "description": "The text at that label, as sent."
                                },
                                "proposal": {
                                    "type": "string",
                                    "description": "change: the replacement text."
                                },
                                "question": {
                                    "type": "string",
                                    "description": "question: what the editor needs from you to fix it."
                                },
                                "why": {
                                    "type": "string"
                                }
                            }
                        }
                    },
                    "revised": {
                        "type": "string",
                        "description": "The text with every change and cut applied; questions left for you. Send it (edited as you like) as the next round's message."
                    },
                    "labelled": {
                        "type": "string",
                        "description": "The text as the editor read it, one labelled sentence per line."
                    },
                    "model": {
                        "type": "string",
                        "description": "The model that edited this round.",
                        "examples": [
                            "haiku"
                        ]
                    },
                    "done": {
                        "type": "boolean",
                        "description": "Whether the session has reached a stopping point. Advice only: you may send more rounds."
                    },
                    "done_reason": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "enum": [
                            "score",
                            "rounds",
                            "stalled",
                            null
                        ],
                        "description": "`score`: reached target_score. `rounds`: reached max_rounds. `stalled`: the score rose less than 5 points over the last two rounds."
                    }
                }
            },
            "EditorialOutput": {
                "allOf": [
                    {
                        "$ref": "#/components/schemas/DeslopOutput"
                    },
                    {
                        "type": "object",
                        "properties": {
                            "ai": {
                                "type": [
                                    "object",
                                    "null"
                                ],
                                "description": "AI detection on the text this round sent. Null when it did not run (`options.detect`: by default only on the round that ends the session), the text was too short, or detection failed.",
                                "properties": {
                                    "ai": {
                                        "type": "number"
                                    },
                                    "label": {
                                        "type": "string"
                                    },
                                    "verdict": {
                                        "type": "string"
                                    },
                                    "version": {
                                        "type": "string"
                                    }
                                }
                            }
                        }
                    }
                ]
            },
            "DetectOutput": {
                "type": "object",
                "required": [
                    "version",
                    "ai",
                    "label",
                    "verdict"
                ],
                "properties": {
                    "version": {
                        "type": "string",
                        "description": "The detector version that produced this result.",
                        "examples": [
                            "detect-v1.1"
                        ]
                    },
                    "ai": {
                        "type": "number",
                        "minimum": 0,
                        "maximum": 1,
                        "description": "Probability that a model wrote most of the text."
                    },
                    "label": {
                        "type": "string",
                        "enum": [
                            "human",
                            "ai",
                            "ai_edited",
                            "humanized",
                            "mixed"
                        ]
                    },
                    "verdict": {
                        "type": "string",
                        "description": "One or two sentences on what the text reads like and why."
                    },
                    "confidence": {
                        "type": [
                            "object",
                            "null"
                        ],
                        "properties": {
                            "level": {
                                "type": "string",
                                "enum": [
                                    "low",
                                    "medium",
                                    "high"
                                ]
                            },
                            "reason": {
                                "type": "string"
                            }
                        }
                    },
                    "breakdown": {
                        "type": [
                            "object",
                            "null"
                        ],
                        "description": "The classifier's probability for each class; sums to 1. Null if the classifier was unavailable.",
                        "properties": {
                            "human": {
                                "type": "number"
                            },
                            "ai": {
                                "type": "number"
                            },
                            "ai_edited": {
                                "type": "number"
                            },
                            "humanized": {
                                "type": "number"
                            }
                        }
                    },
                    "sentences": {
                        "type": "array",
                        "description": "The judge's picks: sentences that read most like a model, quoted exactly.",
                        "items": {
                            "type": "object",
                            "properties": {
                                "text": {
                                    "type": "string"
                                },
                                "why": {
                                    "type": "string"
                                }
                            }
                        }
                    },
                    "examples": {
                        "type": "array",
                        "description": "Sentences that carry known AI patterns, strongest first.",
                        "items": {
                            "type": "object",
                            "properties": {
                                "sentence": {
                                    "type": "string"
                                },
                                "points": {
                                    "type": "number"
                                },
                                "rules": {
                                    "type": "array",
                                    "items": {
                                        "type": "object",
                                        "properties": {
                                            "rule": {
                                                "type": "string"
                                            },
                                            "name": {
                                                "type": "string"
                                            },
                                            "match": {
                                                "type": "string",
                                                "description": "The exact words that matched."
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "tells": {
                        "type": "array",
                        "description": "Each pattern found, with its count and points.",
                        "items": {
                            "type": "object",
                            "properties": {
                                "rule": {
                                    "type": "string"
                                },
                                "name": {
                                    "type": "string"
                                },
                                "count": {
                                    "type": "integer"
                                },
                                "points": {
                                    "type": "number"
                                },
                                "examples": {
                                    "type": "array",
                                    "items": {
                                        "type": "string"
                                    }
                                }
                            }
                        }
                    },
                    "agent": {
                        "type": "object",
                        "properties": {
                            "family": {
                                "type": "string",
                                "enum": [
                                    "claude",
                                    "openai",
                                    "gemini",
                                    "other",
                                    "unknown"
                                ]
                            },
                            "why": {
                                "type": "string"
                            }
                        }
                    },
                    "checks": {
                        "type": "object",
                        "description": "Every check's raw output (linter, classifier, judge), for anyone who wants the working. Shape may grow between versions."
                    }
                }
            },
            "Error": {
                "type": "object",
                "required": [
                    "error"
                ],
                "properties": {
                    "error": {
                        "type": "object",
                        "required": [
                            "type",
                            "message"
                        ],
                        "properties": {
                            "type": {
                                "type": "string",
                                "enum": [
                                    "invalid_request",
                                    "skill_error",
                                    "insufficient_credit",
                                    "upstream_error",
                                    "free_limit",
                                    "rate_limited",
                                    "unauthorized",
                                    "forbidden",
                                    "not_found",
                                    "internal_error"
                                ]
                            },
                            "message": {
                                "type": "string"
                            },
                            "signup_url": {
                                "type": "string",
                                "description": "free_limit only."
                            },
                            "retry_after_seconds": {
                                "type": "integer",
                                "description": "free_limit and rate_limited."
                            },
                            "needed_usd": {
                                "type": "string"
                            },
                            "balance_usd": {
                                "type": "string"
                            },
                            "fields": {
                                "type": "object",
                                "description": "invalid_request only: messages per field."
                            }
                        }
                    }
                }
            }
        },
        "headers": {
            "X-Free-Limit": {
                "schema": {
                    "type": "integer"
                },
                "description": "Keyless calls allowed per hour (keyless calls only)."
            },
            "X-Free-Remaining": {
                "schema": {
                    "type": "integer"
                },
                "description": "Keyless calls left this hour."
            },
            "X-Free-Reset": {
                "schema": {
                    "type": "integer"
                },
                "description": "Seconds until the hourly allowance resets."
            }
        },
        "parameters": {
            "X-P3N-Client": {
                "name": "X-P3N-Client",
                "in": "header",
                "required": false,
                "schema": {
                    "type": "string",
                    "maxLength": 40
                },
                "description": "Optional. Your tool's name (e.g. `my-agent/1.2`), shown per call and as \"By tool\" on the usage page. Without it, the usage page guesses from the User-Agent (curl, python, node, browser)."
            }
        }
    },
    "externalDocs": {
        "description": "Guide, examples, pricing",
        "url": "https://p3n.si/docs"
    },
    "tags": [
        {
            "name": "Skills",
            "description": "Run a skill on text. Short texts answer at once; long ones answer 202 with a run to poll."
        },
        {
            "name": "Deslop sessions",
            "description": "Rounds with the deslop editor: start with the text, then send the revised text and your answers until the score is where you want it."
        },
        {
            "name": "Editorial sessions",
            "description": "Rounds with the editorial editor (deslop plus the AI-artifact checks, and AI detection on the last round): start with the text, then send the revised text and your answers."
        },
        {
            "name": "Runs",
            "description": "Poll a background run."
        },
        {
            "name": "Account",
            "description": "Your key and balance."
        }
    ]
}