{
  "openapi": "3.1.0",
  "info": {
    "title": "Unprofane API",
    "version": "1.0.0",
    "description": "Should I allow this text? One question, answered with the evidence: which words, where, how they were disguised, how severe, what category, and a censored version. The rules route answers at the edge in single-digit milliseconds; the model route runs only for ambiguous text. No request text is stored.",
    "contact": {
      "email": "hello@unprofane.com",
      "url": "https://unprofane.com/docs/"
    },
    "x-limits": {
      "maxTextChars": 10000,
      "maxUsernameChars": 64,
      "maxBatchItems": 100
    }
  },
  "servers": [
    {
      "url": "https://api.unprofane.com"
    }
  ],
  "security": [
    {
      "bearer": []
    }
  ],
  "components": {
    "securitySchemes": {
      "bearer": {
        "type": "http",
        "scheme": "bearer",
        "description": "An API key: up_live_… (billed, needs a plan), up_test_… (free, capped daily) or up_pk_… (publishable, browsers, /v1/check only, needs a plan)."
      }
    },
    "schemas": {
      "CheckRequest": {
        "$schema": "https://json-schema.org/draft/2020-12/schema",
        "type": "object",
        "properties": {
          "text": {
            "type": "string",
            "minLength": 1,
            "maxLength": 10000
          },
          "context": {
            "default": "general",
            "type": "string",
            "enum": [
              "general",
              "username",
              "display_name",
              "comment",
              "chat",
              "gaming",
              "educational",
              "creative",
              "review",
              "custom_text"
            ]
          },
          "policy": {
            "default": "standard",
            "anyOf": [
              {
                "type": "string",
                "enum": [
                  "kids",
                  "teen",
                  "standard",
                  "strict"
                ]
              },
              {
                "type": "string",
                "pattern": "^pol_[A-Za-z0-9]{8,32}$"
              },
              {
                "type": "object",
                "properties": {
                  "mild_profanity": {
                    "type": "string",
                    "enum": [
                      "allow",
                      "review",
                      "block"
                    ]
                  },
                  "profanity": {
                    "type": "string",
                    "enum": [
                      "allow",
                      "review",
                      "block"
                    ]
                  },
                  "sexual": {
                    "type": "string",
                    "enum": [
                      "allow",
                      "review",
                      "block"
                    ]
                  },
                  "insult": {
                    "type": "string",
                    "enum": [
                      "allow",
                      "review",
                      "block"
                    ]
                  },
                  "slur": {
                    "type": "string",
                    "enum": [
                      "allow",
                      "review",
                      "block"
                    ]
                  },
                  "threat": {
                    "type": "string",
                    "enum": [
                      "allow",
                      "review",
                      "block"
                    ]
                  },
                  "rude": {
                    "type": "string",
                    "enum": [
                      "allow",
                      "review",
                      "block"
                    ]
                  },
                  "sexual_minors": {
                    "type": "string",
                    "enum": [
                      "allow",
                      "review",
                      "block"
                    ]
                  },
                  "self_harm": {
                    "type": "string",
                    "enum": [
                      "allow",
                      "review",
                      "block"
                    ]
                  },
                  "reserved": {
                    "type": "string",
                    "enum": [
                      "allow",
                      "review",
                      "block"
                    ]
                  }
                },
                "additionalProperties": false
              }
            ]
          },
          "mode": {
            "default": "balanced",
            "type": "string",
            "enum": [
              "fast",
              "balanced",
              "thorough"
            ]
          },
          "language": {
            "default": "auto",
            "type": "string",
            "enum": [
              "auto",
              "en",
              "es",
              "pt",
              "fr",
              "de",
              "it",
              "nl",
              "pl",
              "tr",
              "ru",
              "ar",
              "he",
              "hi",
              "id",
              "ja"
            ]
          },
          "mask": {
            "default": "asterisk",
            "type": "string",
            "enum": [
              "asterisk",
              "first_letter",
              "grawlix",
              "remove"
            ]
          },
          "engine": {
            "type": "string",
            "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
          },
          "lists": {
            "type": "object",
            "properties": {
              "allow": {
                "maxItems": 50,
                "type": "array",
                "items": {
                  "type": "string",
                  "minLength": 1,
                  "maxLength": 64
                }
              },
              "block": {
                "maxItems": 50,
                "type": "array",
                "items": {
                  "type": "string",
                  "minLength": 1,
                  "maxLength": 64
                }
              }
            },
            "additionalProperties": false
          }
        },
        "required": [
          "text"
        ],
        "additionalProperties": false
      },
      "CheckResponse": {
        "$schema": "https://json-schema.org/draft/2020-12/schema",
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "pattern": "^chk_[A-Za-z0-9]{16,32}$"
          },
          "allowed": {
            "type": "boolean"
          },
          "action": {
            "type": "string",
            "enum": [
              "allow",
              "review",
              "block"
            ]
          },
          "score": {
            "type": "number",
            "minimum": 0,
            "maximum": 1
          },
          "severity": {
            "type": "string",
            "enum": [
              "none",
              "mild",
              "moderate",
              "strong",
              "extreme"
            ]
          },
          "categories": {
            "type": "object",
            "properties": {
              "mild_profanity": {
                "type": "number",
                "minimum": 0,
                "maximum": 1
              },
              "profanity": {
                "type": "number",
                "minimum": 0,
                "maximum": 1
              },
              "sexual": {
                "type": "number",
                "minimum": 0,
                "maximum": 1
              },
              "insult": {
                "type": "number",
                "minimum": 0,
                "maximum": 1
              },
              "slur": {
                "type": "number",
                "minimum": 0,
                "maximum": 1
              },
              "threat": {
                "type": "number",
                "minimum": 0,
                "maximum": 1
              },
              "rude": {
                "type": "number",
                "minimum": 0,
                "maximum": 1
              },
              "sexual_minors": {
                "type": "number",
                "minimum": 0,
                "maximum": 1
              },
              "self_harm": {
                "type": "number",
                "minimum": 0,
                "maximum": 1
              },
              "reserved": {
                "type": "number",
                "minimum": 0,
                "maximum": 1
              }
            },
            "required": [
              "mild_profanity",
              "profanity",
              "sexual",
              "insult",
              "slur",
              "threat",
              "rude",
              "sexual_minors",
              "self_harm",
              "reserved"
            ],
            "additionalProperties": false
          },
          "obfuscated": {
            "type": "boolean"
          },
          "evasion": {
            "type": "array",
            "items": {
              "type": "string",
              "enum": [
                "homoglyph",
                "zero_width",
                "separator",
                "leetspeak",
                "repeated_chars",
                "diacritics",
                "mixed_script",
                "fullwidth",
                "combining_marks",
                "phonetic",
                "reversed",
                "concatenation",
                "case_mixing",
                "self_censored"
              ]
            }
          },
          "matches": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "start": {
                  "type": "integer",
                  "minimum": 0,
                  "maximum": 9007199254740991
                },
                "end": {
                  "type": "integer",
                  "minimum": 0,
                  "maximum": 9007199254740991
                },
                "text": {
                  "type": "string"
                },
                "normalized": {
                  "type": "string"
                },
                "term_id": {
                  "type": "string"
                },
                "category": {
                  "type": "string",
                  "enum": [
                    "profanity",
                    "sexual",
                    "insult",
                    "slur",
                    "threat",
                    "reserved"
                  ]
                },
                "severity": {
                  "type": "string",
                  "enum": [
                    "none",
                    "mild",
                    "moderate",
                    "strong",
                    "extreme"
                  ]
                },
                "evasion": {
                  "type": "array",
                  "items": {
                    "type": "string",
                    "enum": [
                      "homoglyph",
                      "zero_width",
                      "separator",
                      "leetspeak",
                      "repeated_chars",
                      "diacritics",
                      "mixed_script",
                      "fullwidth",
                      "combining_marks",
                      "phonetic",
                      "reversed",
                      "concatenation",
                      "case_mixing",
                      "self_censored"
                    ]
                  }
                }
              },
              "required": [
                "start",
                "end",
                "text",
                "normalized",
                "term_id",
                "category",
                "severity",
                "evasion"
              ],
              "additionalProperties": false
            }
          },
          "censored": {
            "type": "string"
          },
          "reason": {
            "type": "string"
          },
          "language": {
            "type": "object",
            "properties": {
              "detected": {
                "type": "string"
              },
              "confidence": {
                "type": "number",
                "minimum": 0,
                "maximum": 1
              }
            },
            "required": [
              "detected",
              "confidence"
            ],
            "additionalProperties": false
          },
          "engine": {
            "type": "object",
            "properties": {
              "version": {
                "type": "string",
                "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
              },
              "route": {
                "type": "string",
                "enum": [
                  "rules",
                  "model",
                  "cache"
                ]
              },
              "degraded": {
                "type": "boolean"
              }
            },
            "required": [
              "version",
              "route",
              "degraded"
            ],
            "additionalProperties": false
          },
          "timing_ms": {
            "type": "number",
            "minimum": 0
          }
        },
        "required": [
          "id",
          "allowed",
          "action",
          "score",
          "severity",
          "categories",
          "obfuscated",
          "evasion",
          "matches",
          "censored",
          "reason",
          "language",
          "engine",
          "timing_ms"
        ],
        "additionalProperties": false
      },
      "BatchRequest": {
        "$schema": "https://json-schema.org/draft/2020-12/schema",
        "type": "object",
        "properties": {
          "items": {
            "minItems": 1,
            "maxItems": 100,
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "id": {
                  "type": "string",
                  "minLength": 1,
                  "maxLength": 64
                },
                "text": {
                  "type": "string",
                  "minLength": 1,
                  "maxLength": 10000
                },
                "context": {
                  "type": "string",
                  "enum": [
                    "general",
                    "username",
                    "display_name",
                    "comment",
                    "chat",
                    "gaming",
                    "educational",
                    "creative",
                    "review",
                    "custom_text"
                  ]
                },
                "policy": {
                  "anyOf": [
                    {
                      "type": "string",
                      "enum": [
                        "kids",
                        "teen",
                        "standard",
                        "strict"
                      ]
                    },
                    {
                      "type": "string",
                      "pattern": "^pol_[A-Za-z0-9]{8,32}$"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "mild_profanity": {
                          "type": "string",
                          "enum": [
                            "allow",
                            "review",
                            "block"
                          ]
                        },
                        "profanity": {
                          "type": "string",
                          "enum": [
                            "allow",
                            "review",
                            "block"
                          ]
                        },
                        "sexual": {
                          "type": "string",
                          "enum": [
                            "allow",
                            "review",
                            "block"
                          ]
                        },
                        "insult": {
                          "type": "string",
                          "enum": [
                            "allow",
                            "review",
                            "block"
                          ]
                        },
                        "slur": {
                          "type": "string",
                          "enum": [
                            "allow",
                            "review",
                            "block"
                          ]
                        },
                        "threat": {
                          "type": "string",
                          "enum": [
                            "allow",
                            "review",
                            "block"
                          ]
                        },
                        "rude": {
                          "type": "string",
                          "enum": [
                            "allow",
                            "review",
                            "block"
                          ]
                        },
                        "sexual_minors": {
                          "type": "string",
                          "enum": [
                            "allow",
                            "review",
                            "block"
                          ]
                        },
                        "self_harm": {
                          "type": "string",
                          "enum": [
                            "allow",
                            "review",
                            "block"
                          ]
                        },
                        "reserved": {
                          "type": "string",
                          "enum": [
                            "allow",
                            "review",
                            "block"
                          ]
                        }
                      },
                      "additionalProperties": false
                    }
                  ]
                }
              },
              "required": [
                "id",
                "text"
              ],
              "additionalProperties": false
            }
          },
          "context": {
            "default": "general",
            "type": "string",
            "enum": [
              "general",
              "username",
              "display_name",
              "comment",
              "chat",
              "gaming",
              "educational",
              "creative",
              "review",
              "custom_text"
            ]
          },
          "policy": {
            "default": "standard",
            "anyOf": [
              {
                "type": "string",
                "enum": [
                  "kids",
                  "teen",
                  "standard",
                  "strict"
                ]
              },
              {
                "type": "string",
                "pattern": "^pol_[A-Za-z0-9]{8,32}$"
              },
              {
                "type": "object",
                "properties": {
                  "mild_profanity": {
                    "type": "string",
                    "enum": [
                      "allow",
                      "review",
                      "block"
                    ]
                  },
                  "profanity": {
                    "type": "string",
                    "enum": [
                      "allow",
                      "review",
                      "block"
                    ]
                  },
                  "sexual": {
                    "type": "string",
                    "enum": [
                      "allow",
                      "review",
                      "block"
                    ]
                  },
                  "insult": {
                    "type": "string",
                    "enum": [
                      "allow",
                      "review",
                      "block"
                    ]
                  },
                  "slur": {
                    "type": "string",
                    "enum": [
                      "allow",
                      "review",
                      "block"
                    ]
                  },
                  "threat": {
                    "type": "string",
                    "enum": [
                      "allow",
                      "review",
                      "block"
                    ]
                  },
                  "rude": {
                    "type": "string",
                    "enum": [
                      "allow",
                      "review",
                      "block"
                    ]
                  },
                  "sexual_minors": {
                    "type": "string",
                    "enum": [
                      "allow",
                      "review",
                      "block"
                    ]
                  },
                  "self_harm": {
                    "type": "string",
                    "enum": [
                      "allow",
                      "review",
                      "block"
                    ]
                  },
                  "reserved": {
                    "type": "string",
                    "enum": [
                      "allow",
                      "review",
                      "block"
                    ]
                  }
                },
                "additionalProperties": false
              }
            ]
          },
          "mode": {
            "default": "balanced",
            "type": "string",
            "enum": [
              "fast",
              "balanced",
              "thorough"
            ]
          },
          "mask": {
            "default": "asterisk",
            "type": "string",
            "enum": [
              "asterisk",
              "first_letter",
              "grawlix",
              "remove"
            ]
          },
          "engine": {
            "type": "string",
            "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
          },
          "lists": {
            "type": "object",
            "properties": {
              "allow": {
                "maxItems": 50,
                "type": "array",
                "items": {
                  "type": "string",
                  "minLength": 1,
                  "maxLength": 64
                }
              },
              "block": {
                "maxItems": 50,
                "type": "array",
                "items": {
                  "type": "string",
                  "minLength": 1,
                  "maxLength": 64
                }
              }
            },
            "additionalProperties": false
          }
        },
        "required": [
          "items"
        ],
        "additionalProperties": false
      },
      "BatchResponse": {
        "$schema": "https://json-schema.org/draft/2020-12/schema",
        "type": "object",
        "properties": {
          "results": {
            "type": "array",
            "items": {
              "anyOf": [
                {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string"
                    },
                    "result": {
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "string",
                          "pattern": "^chk_[A-Za-z0-9]{16,32}$"
                        },
                        "allowed": {
                          "type": "boolean"
                        },
                        "action": {
                          "type": "string",
                          "enum": [
                            "allow",
                            "review",
                            "block"
                          ]
                        },
                        "score": {
                          "type": "number",
                          "minimum": 0,
                          "maximum": 1
                        },
                        "severity": {
                          "type": "string",
                          "enum": [
                            "none",
                            "mild",
                            "moderate",
                            "strong",
                            "extreme"
                          ]
                        },
                        "categories": {
                          "type": "object",
                          "properties": {
                            "mild_profanity": {
                              "type": "number",
                              "minimum": 0,
                              "maximum": 1
                            },
                            "profanity": {
                              "type": "number",
                              "minimum": 0,
                              "maximum": 1
                            },
                            "sexual": {
                              "type": "number",
                              "minimum": 0,
                              "maximum": 1
                            },
                            "insult": {
                              "type": "number",
                              "minimum": 0,
                              "maximum": 1
                            },
                            "slur": {
                              "type": "number",
                              "minimum": 0,
                              "maximum": 1
                            },
                            "threat": {
                              "type": "number",
                              "minimum": 0,
                              "maximum": 1
                            },
                            "rude": {
                              "type": "number",
                              "minimum": 0,
                              "maximum": 1
                            },
                            "sexual_minors": {
                              "type": "number",
                              "minimum": 0,
                              "maximum": 1
                            },
                            "self_harm": {
                              "type": "number",
                              "minimum": 0,
                              "maximum": 1
                            },
                            "reserved": {
                              "type": "number",
                              "minimum": 0,
                              "maximum": 1
                            }
                          },
                          "required": [
                            "mild_profanity",
                            "profanity",
                            "sexual",
                            "insult",
                            "slur",
                            "threat",
                            "rude",
                            "sexual_minors",
                            "self_harm",
                            "reserved"
                          ],
                          "additionalProperties": false
                        },
                        "obfuscated": {
                          "type": "boolean"
                        },
                        "evasion": {
                          "type": "array",
                          "items": {
                            "type": "string",
                            "enum": [
                              "homoglyph",
                              "zero_width",
                              "separator",
                              "leetspeak",
                              "repeated_chars",
                              "diacritics",
                              "mixed_script",
                              "fullwidth",
                              "combining_marks",
                              "phonetic",
                              "reversed",
                              "concatenation",
                              "case_mixing",
                              "self_censored"
                            ]
                          }
                        },
                        "matches": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "start": {
                                "type": "integer",
                                "minimum": 0,
                                "maximum": 9007199254740991
                              },
                              "end": {
                                "type": "integer",
                                "minimum": 0,
                                "maximum": 9007199254740991
                              },
                              "text": {
                                "type": "string"
                              },
                              "normalized": {
                                "type": "string"
                              },
                              "term_id": {
                                "type": "string"
                              },
                              "category": {
                                "type": "string",
                                "enum": [
                                  "profanity",
                                  "sexual",
                                  "insult",
                                  "slur",
                                  "threat",
                                  "reserved"
                                ]
                              },
                              "severity": {
                                "type": "string",
                                "enum": [
                                  "none",
                                  "mild",
                                  "moderate",
                                  "strong",
                                  "extreme"
                                ]
                              },
                              "evasion": {
                                "type": "array",
                                "items": {
                                  "type": "string",
                                  "enum": [
                                    "homoglyph",
                                    "zero_width",
                                    "separator",
                                    "leetspeak",
                                    "repeated_chars",
                                    "diacritics",
                                    "mixed_script",
                                    "fullwidth",
                                    "combining_marks",
                                    "phonetic",
                                    "reversed",
                                    "concatenation",
                                    "case_mixing",
                                    "self_censored"
                                  ]
                                }
                              }
                            },
                            "required": [
                              "start",
                              "end",
                              "text",
                              "normalized",
                              "term_id",
                              "category",
                              "severity",
                              "evasion"
                            ],
                            "additionalProperties": false
                          }
                        },
                        "censored": {
                          "type": "string"
                        },
                        "reason": {
                          "type": "string"
                        },
                        "language": {
                          "type": "object",
                          "properties": {
                            "detected": {
                              "type": "string"
                            },
                            "confidence": {
                              "type": "number",
                              "minimum": 0,
                              "maximum": 1
                            }
                          },
                          "required": [
                            "detected",
                            "confidence"
                          ],
                          "additionalProperties": false
                        },
                        "engine": {
                          "type": "object",
                          "properties": {
                            "version": {
                              "type": "string",
                              "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
                            },
                            "route": {
                              "type": "string",
                              "enum": [
                                "rules",
                                "model",
                                "cache"
                              ]
                            },
                            "degraded": {
                              "type": "boolean"
                            }
                          },
                          "required": [
                            "version",
                            "route",
                            "degraded"
                          ],
                          "additionalProperties": false
                        },
                        "timing_ms": {
                          "type": "number",
                          "minimum": 0
                        }
                      },
                      "required": [
                        "id",
                        "allowed",
                        "action",
                        "score",
                        "severity",
                        "categories",
                        "obfuscated",
                        "evasion",
                        "matches",
                        "censored",
                        "reason",
                        "language",
                        "engine",
                        "timing_ms"
                      ],
                      "additionalProperties": false
                    }
                  },
                  "required": [
                    "id",
                    "result"
                  ],
                  "additionalProperties": false
                },
                {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string"
                    },
                    "error": {
                      "type": "object",
                      "properties": {
                        "type": {
                          "type": "string"
                        },
                        "title": {
                          "type": "string"
                        },
                        "detail": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "type",
                        "title"
                      ],
                      "additionalProperties": false
                    }
                  },
                  "required": [
                    "id",
                    "error"
                  ],
                  "additionalProperties": false
                }
              ]
            }
          },
          "counted": {
            "type": "integer",
            "minimum": 0,
            "maximum": 9007199254740991
          }
        },
        "required": [
          "results",
          "counted"
        ],
        "additionalProperties": false
      },
      "FeedbackRequest": {
        "$schema": "https://json-schema.org/draft/2020-12/schema",
        "type": "object",
        "properties": {
          "check_id": {
            "type": "string",
            "pattern": "^chk_[A-Za-z0-9]{16,32}$"
          },
          "verdict": {
            "type": "string",
            "enum": [
              "false_positive",
              "false_negative",
              "correct"
            ]
          },
          "expected_action": {
            "type": "string",
            "enum": [
              "allow",
              "review",
              "block"
            ]
          },
          "note": {
            "type": "string",
            "maxLength": 500
          },
          "text": {
            "type": "string",
            "maxLength": 10000
          }
        },
        "required": [
          "check_id",
          "verdict"
        ],
        "additionalProperties": false
      },
      "FeedbackResponse": {
        "$schema": "https://json-schema.org/draft/2020-12/schema",
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "received": {
            "type": "boolean"
          }
        },
        "required": [
          "id",
          "received"
        ],
        "additionalProperties": false
      },
      "UsageResponse": {
        "$schema": "https://json-schema.org/draft/2020-12/schema",
        "type": "object",
        "properties": {
          "period": {
            "type": "object",
            "properties": {
              "start": {
                "type": "string"
              },
              "end": {
                "type": "string"
              }
            },
            "required": [
              "start",
              "end"
            ],
            "additionalProperties": false
          },
          "plan": {
            "type": "string"
          },
          "checks": {
            "type": "integer",
            "minimum": 0,
            "maximum": 9007199254740991
          },
          "included": {
            "anyOf": [
              {
                "type": "integer",
                "minimum": 0,
                "maximum": 9007199254740991
              },
              {
                "type": "null"
              }
            ]
          },
          "overage": {
            "type": "integer",
            "minimum": 0,
            "maximum": 9007199254740991
          },
          "routes": {
            "type": "object",
            "properties": {
              "rules": {
                "type": "number"
              },
              "model": {
                "type": "number"
              },
              "cache": {
                "type": "number"
              }
            },
            "required": [
              "rules",
              "model",
              "cache"
            ],
            "additionalProperties": false
          },
          "degraded": {
            "type": "number"
          }
        },
        "required": [
          "period",
          "plan",
          "checks",
          "included",
          "overage",
          "routes",
          "degraded"
        ],
        "additionalProperties": false
      },
      "List": {
        "$schema": "https://json-schema.org/draft/2020-12/schema",
        "type": "object",
        "properties": {
          "kind": {
            "type": "string",
            "enum": [
              "allow",
              "block",
              "reserved"
            ]
          },
          "terms": {
            "maxItems": 5000,
            "type": "array",
            "items": {
              "type": "string",
              "minLength": 1,
              "maxLength": 64
            }
          },
          "version": {
            "type": "integer",
            "minimum": 0,
            "maximum": 9007199254740991
          }
        },
        "required": [
          "kind",
          "terms",
          "version"
        ],
        "additionalProperties": false
      },
      "ListPut": {
        "$schema": "https://json-schema.org/draft/2020-12/schema",
        "type": "object",
        "properties": {
          "terms": {
            "maxItems": 5000,
            "type": "array",
            "items": {
              "type": "string",
              "minLength": 1,
              "maxLength": 64
            }
          }
        },
        "required": [
          "terms"
        ],
        "additionalProperties": false
      },
      "Health": {
        "$schema": "https://json-schema.org/draft/2020-12/schema",
        "type": "object",
        "properties": {
          "ok": {
            "type": "boolean",
            "const": true
          },
          "engine": {
            "type": "string",
            "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
          },
          "lexicon": {
            "type": "string"
          }
        },
        "required": [
          "ok",
          "engine",
          "lexicon"
        ],
        "additionalProperties": false
      },
      "Problem": {
        "type": "object",
        "properties": {
          "type": {
            "type": "string",
            "format": "uri",
            "enum": [
              "https://unprofane.com/docs/errors/invalid-request",
              "https://unprofane.com/docs/errors/unauthorized",
              "https://unprofane.com/docs/errors/key-revoked",
              "https://unprofane.com/docs/errors/forbidden-origin",
              "https://unprofane.com/docs/errors/forbidden-secret-cors",
              "https://unprofane.com/docs/errors/not-found",
              "https://unprofane.com/docs/errors/method-not-allowed",
              "https://unprofane.com/docs/errors/unsupported-media-type",
              "https://unprofane.com/docs/errors/payload-too-large",
              "https://unprofane.com/docs/errors/subscription-required",
              "https://unprofane.com/docs/errors/quota-exceeded",
              "https://unprofane.com/docs/errors/rate-limited",
              "https://unprofane.com/docs/errors/test-key-daily-cap",
              "https://unprofane.com/docs/errors/engine-unknown",
              "https://unprofane.com/docs/errors/misconfigured"
            ]
          },
          "title": {
            "type": "string"
          },
          "status": {
            "type": "integer"
          },
          "detail": {
            "type": "string"
          }
        },
        "required": [
          "type",
          "title",
          "status"
        ]
      }
    }
  },
  "paths": {
    "/v1/check": {
      "post": {
        "operationId": "check",
        "summary": "Check one text",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CheckRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The decision with its evidence.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CheckResponse"
                }
              }
            }
          },
          "400": {
            "description": "The request body is not valid. / No such engine version.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "No valid API key. / This API key was revoked.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "402": {
            "description": "A plan is required.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "This origin is not allowed for this publishable key. / Secret keys cannot be used from a browser.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "413": {
            "description": "The request body is too large.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "415": {
            "description": "Send application/json.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests. / This plan’s monthly checks are used up. / Test keys are capped per day.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/v1/check/batch": {
      "post": {
        "operationId": "checkBatch",
        "summary": "Check up to 100 texts",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/BatchRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Results in order; one bad item never fails the batch.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BatchResponse"
                }
              }
            }
          },
          "400": {
            "description": "The request body is not valid.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "No valid API key. / This API key was revoked.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "402": {
            "description": "A plan is required.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "413": {
            "description": "The request body is too large.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "415": {
            "description": "Send application/json.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests. / This plan’s monthly checks are used up. / Test keys are capped per day.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/v1/feedback": {
      "post": {
        "operationId": "feedback",
        "summary": "Report a wrong result",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/FeedbackRequest"
              }
            }
          }
        },
        "responses": {
          "202": {
            "description": "Recorded.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/FeedbackResponse"
                }
              }
            }
          },
          "400": {
            "description": "The request body is not valid.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "No valid API key. / This API key was revoked.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "402": {
            "description": "A plan is required.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "413": {
            "description": "The request body is too large.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "415": {
            "description": "Send application/json.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests. / This plan’s monthly checks are used up. / Test keys are capped per day.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/v1/usage": {
      "get": {
        "operationId": "usage",
        "summary": "This period’s usage",
        "responses": {
          "200": {
            "description": "Checks, allowance, overage and route mix.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/UsageResponse"
                }
              }
            }
          },
          "401": {
            "description": "No valid API key. / This API key was revoked.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "402": {
            "description": "A plan is required.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "413": {
            "description": "The request body is too large.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "415": {
            "description": "Send application/json.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests. / This plan’s monthly checks are used up. / Test keys are capped per day.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/v1/projects/{id}/lists/{kind}": {
      "parameters": [
        {
          "name": "id",
          "in": "path",
          "required": true,
          "schema": {
            "type": "string",
            "pattern": "^prj_[A-Za-z0-9]{20}$"
          }
        },
        {
          "name": "kind",
          "in": "path",
          "required": true,
          "schema": {
            "type": "string",
            "enum": [
              "allow",
              "block",
              "reserved"
            ]
          }
        }
      ],
      "get": {
        "operationId": "getList",
        "summary": "Read a project list",
        "responses": {
          "200": {
            "description": "The list.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/List"
                }
              }
            }
          },
          "401": {
            "description": "No valid API key. / This API key was revoked.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "402": {
            "description": "A plan is required.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "No such resource.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "413": {
            "description": "The request body is too large.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "415": {
            "description": "Send application/json.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests. / This plan’s monthly checks are used up. / Test keys are capped per day.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      },
      "put": {
        "operationId": "putList",
        "summary": "Replace a project list",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ListPut"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The list as stored.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/List"
                }
              }
            }
          },
          "400": {
            "description": "The request body is not valid.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "No valid API key. / This API key was revoked.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "402": {
            "description": "A plan is required.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "No such resource.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "413": {
            "description": "The request body is too large.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "415": {
            "description": "Send application/json.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests. / This plan’s monthly checks are used up. / Test keys are capped per day.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      },
      "delete": {
        "operationId": "deleteList",
        "summary": "Empty a project list",
        "responses": {
          "204": {
            "description": "Emptied."
          },
          "401": {
            "description": "No valid API key. / This API key was revoked.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "402": {
            "description": "A plan is required.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "No such resource.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "413": {
            "description": "The request body is too large.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "415": {
            "description": "Send application/json.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests. / This plan’s monthly checks are used up. / Test keys are capped per day.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/health": {
      "get": {
        "operationId": "health",
        "security": [],
        "summary": "Liveness",
        "responses": {
          "200": {
            "description": "The engine and lexicon in service.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Health"
                }
              }
            }
          }
        }
      }
    },
    "/v1alpha1/comments:analyze": {
      "post": {
        "operationId": "perspectiveAnalyze",
        "summary": "Perspective-compatible comments:analyze",
        "description": "Byte-compatible with Google’s Perspective API v1alpha1. The key may be sent as `?key=` as Perspective clients do. Errors use Google’s envelope, not problem details.",
        "security": [
          {
            "bearer": []
          },
          {
            "query_key": []
          }
        ],
        "responses": {
          "200": {
            "description": "attributeScores per requested attribute."
          },
          "400": {
            "description": "Google-shaped error."
          }
        }
      }
    }
  }
}