{
  "openapi": "3.0.1",
  "info": {
    "title": "Distributed Proofreaders API",
    "description": "An API to access various components in the DP system.",
    "contact": {
      "name": "Distributed Proofreaders",
      "url": "https://www.pgdp.net"
    },
    "license": {
      "name": "GPL2",
      "url": "http://opensource.org/licenses/GPL-2.0"
    },
    "version": "1.0.0"
  },
  "servers": [
    {
      "url": "https://www.pgdp.net/api/v1",
      "description": "Production"
    },
    {
      "url": "https://www.pgdp.org/api/v1",
      "description": "Test"
    },
    {
      "url": "https://www.pgdp.org/api-dev/v1",
      "description": "Development"
    }
  ],
  "paths": {
    "/projects": {
      "get": {
        "tags": [
          "project"
        ],
        "description": "Search for projects. <br><br> If different parameters are included they are ANDed together. To send multiple values of the same parameter to OR together, append the name with [] (e.g. projectid[]). <br><br> Results are paginated with a default page size of 20 and can be controlled with the `page` and `per_page` query parameters. See also the `X-Results-Total` and `Links` headers in the response.",
        "parameters": [
          {
            "name": "projectid",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "title",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Title is treated as a subsearch"
          },
          {
            "name": "author",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Author is treated as a subsearch"
          },
          {
            "name": "languages",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Languages is treated as a subsearch"
          },
          {
            "name": "genre",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "difficulty",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "special_day",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "project_manager",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "pg_ebook_number",
            "in": "query",
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "state",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "in_smoothreading",
            "in": "query",
            "required": false,
            "schema": {
              "type": "boolean"
            }
          },
          {
            "name": "field",
            "description": "Field to return, if not set all fields are returned. To request multiple fields, append with [] and pass one per desired field (e.g. field[]=projectid&field[]=author).",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "page",
            "description": "Page of results to return",
            "in": "query",
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "per_page",
            "description": "Number of entries per page",
            "in": "query",
            "schema": {
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "List of projects found in search",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/project"
                  }
                }
              }
            },
            "headers": {
              "X-Results-Total": {
                "schema": {
                  "type": "integer"
                },
                "description": "Total number of projects matching query"
              },
              "Links": {
                "schema": {
                  "type": "string"
                },
                "description": "Links for accessing paginated response in RFC-8288 format"
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimitExceeded"
          },
          "default": {
            "$ref": "#/components/responses/UnexpectedError"
          }
        }
      },
      "post": {
        "tags": [
          "project"
        ],
        "description": "Create a new project.",
        "requestBody": {
          "description": "Project details",
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/project"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Created project",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/project"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/InvalidValue"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimitExceeded"
          },
          "default": {
            "$ref": "#/components/responses/UnexpectedError"
          }
        }
      }
    },
    "/projects/charsuites": {
      "get": {
        "tags": [
          "project"
        ],
        "description": "Returns a list of valid project character suites",
        "parameters": [
          {
            "name": "enabled",
            "in": "query",
            "description": "Only return enabled character suites",
            "required": false,
            "schema": {
              "type": "boolean"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "List of valid character suites",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/charsuite"
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimitExceeded"
          },
          "default": {
            "$ref": "#/components/responses/UnexpectedError"
          }
        }
      }
    },
    "/projects/difficulties": {
      "get": {
        "tags": [
          "project"
        ],
        "description": "Returns a list of valid project difficulties",
        "responses": {
          "200": {
            "description": "List of difficulties",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "type": "string"
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimitExceeded"
          },
          "default": {
            "$ref": "#/components/responses/UnexpectedError"
          }
        }
      }
    },
    "/projects/genres": {
      "get": {
        "tags": [
          "project"
        ],
        "description": "Returns a list of valid project genres",
        "responses": {
          "200": {
            "description": "List of genres",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "type": "string"
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimitExceeded"
          },
          "default": {
            "$ref": "#/components/responses/UnexpectedError"
          }
        }
      }
    },
    "/projects/imagesources": {
      "get": {
        "tags": [
          "project"
        ],
        "description": "Returns a list of valid project image sources",
        "parameters": [
          {
            "name": "enabled",
            "in": "query",
            "description": "Only return enabled image sources",
            "required": false,
            "schema": {
              "type": "boolean"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "List of valid image sources",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/image_source"
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimitExceeded"
          },
          "default": {
            "$ref": "#/components/responses/UnexpectedError"
          }
        }
      }
    },
    "/projects/languages": {
      "get": {
        "tags": [
          "project"
        ],
        "description": "Returns a list of valid project languages",
        "responses": {
          "200": {
            "description": "List of languages",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "type": "string"
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimitExceeded"
          },
          "default": {
            "$ref": "#/components/responses/UnexpectedError"
          }
        }
      }
    },
    "/projects/pagerounds": {
      "get": {
        "tags": [
          "project"
        ],
        "description": "Returns a list of valid page rounds",
        "responses": {
          "200": {
            "description": "List of page rounds",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "type": "string"
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimitExceeded"
          },
          "default": {
            "$ref": "#/components/responses/UnexpectedError"
          }
        }
      }
    },
    "/projects/specialdays": {
      "get": {
        "tags": [
          "project"
        ],
        "description": "Returns a list of valid special days",
        "parameters": [
          {
            "name": "enabled",
            "in": "query",
            "description": "Only return enabled special days",
            "required": false,
            "schema": {
              "type": "boolean"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "List of special days",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/special_day"
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimitExceeded"
          },
          "default": {
            "$ref": "#/components/responses/UnexpectedError"
          }
        }
      }
    },
    "/projects/states": {
      "get": {
        "tags": [
          "project"
        ],
        "description": "Returns a list of valid project states",
        "responses": {
          "200": {
            "description": "List of states",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "type": "string"
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimitExceeded"
          },
          "default": {
            "$ref": "#/components/responses/UnexpectedError"
          }
        }
      }
    },
    "/projects/holdstates": {
      "get": {
        "tags": [
          "project"
        ],
        "description": "Returns a list of holdable project states",
        "responses": {
          "200": {
            "description": "List of holdable states",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "type": "string"
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimitExceeded"
          },
          "default": {
            "$ref": "#/components/responses/UnexpectedError"
          }
        }
      }
    },
    "/projects/{projectid}": {
      "get": {
        "tags": [
          "project"
        ],
        "description": "Returns details about a project",
        "parameters": [
          {
            "name": "projectid",
            "in": "path",
            "description": "ID of project to return",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "field",
            "description": "Field to return, if not set all fields are returned. To request multiple fields, append with [] and pass one per desired field (e.g. field[]=projectid&field[]=author).",
            "in": "query",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "project response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/project"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimitExceeded"
          },
          "default": {
            "$ref": "#/components/responses/UnexpectedError"
          }
        }
      },
      "put": {
        "tags": [
          "project"
        ],
        "description": "Update an existing project. A partial object can be sent and only those fields included will be updated.",
        "parameters": [
          {
            "name": "projectid",
            "in": "path",
            "description": "ID of project to update",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "description": "Project details",
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/project"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Updated project",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/project"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/InvalidValue"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimitExceeded"
          },
          "default": {
            "$ref": "#/components/responses/UnexpectedError"
          }
        }
      }
    },
    "/projects/{projectid}/artifacts/{stage}": {
      "get": {
        "tags": [
          "project"
        ],
        "description": "Gets the project artifacts for the given stage.",
        "parameters": [
          {
            "name": "projectid",
            "in": "path",
            "description": "ID of project",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "stage",
            "in": "path",
            "description": "Project stage",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Requested project artifacts",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/project_artifacts"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimitExceeded"
          },
          "default": {
            "$ref": "#/components/responses/UnexpectedError"
          }
        }
      }
    },
    "/projects/{projectid}/holdstates": {
      "get": {
        "tags": [
          "project"
        ],
        "description": "Returns a list of hold states for the project",
        "parameters": [
          {
            "name": "projectid",
            "in": "path",
            "description": "ID of project",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "List of current project hold states",
            "content": {
              "application/json": {
                "schema": {
                  "items": {
                    "type": "string"
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimitExceeded"
          },
          "default": {
            "$ref": "#/components/responses/UnexpectedError"
          }
        }
      },
      "put": {
        "tags": [
          "project"
        ],
        "description": "Sets the holdable states for a project",
        "parameters": [
          {
            "name": "projectid",
            "in": "path",
            "description": "ID of project",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "description": "List of holdable states to set",
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "items": {
                  "type": "string"
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "List of current project hold states",
            "content": {
              "application/json": {
                "schema": {
                  "items": {
                    "type": "string"
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/InvalidValue"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimitExceeded"
          },
          "default": {
            "$ref": "#/components/responses/UnexpectedError"
          }
        }
      }
    },
    "/projects/{projectid}/wordlists/{type}": {
      "get": {
        "tags": [
          "project"
        ],
        "description": "Gets a project's word list",
        "parameters": [
          {
            "name": "projectid",
            "in": "path",
            "description": "ID of project",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "type",
            "in": "path",
            "description": "Word list type",
            "required": true,
            "schema": {
              "type": "string",
              "enum": [
                "good",
                "bad"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Requested project word list",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/wordlist"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimitExceeded"
          },
          "default": {
            "$ref": "#/components/responses/UnexpectedError"
          }
        }
      },
      "put": {
        "tags": [
          "project"
        ],
        "description": "Replaces a project's word list",
        "parameters": [
          {
            "name": "projectid",
            "in": "path",
            "description": "ID of project",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "type",
            "in": "path",
            "description": "Word list type",
            "required": true,
            "schema": {
              "type": "string",
              "enum": [
                "good",
                "bad"
              ]
            }
          }
        ],
        "requestBody": {
          "description": "List of replacement words",
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/wordlist"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "wordlist saved",
            "content": {}
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimitExceeded"
          },
          "default": {
            "$ref": "#/components/responses/UnexpectedError"
          }
        }
      }
    },
    "/projects/{projectid}/pages": {
      "get": {
        "tags": [
          "project"
        ],
        "description": "Gets a list of project pages",
        "parameters": [
          {
            "name": "projectid",
            "in": "path",
            "description": "ID of project",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "List of a project's page names",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/project_page_index"
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimitExceeded"
          },
          "default": {
            "$ref": "#/components/responses/UnexpectedError"
          }
        }
      }
    },
    "/projects/{projectid}/pagedetails": {
      "get": {
        "tags": [
          "project"
        ],
        "description": "Gets all details about a project's pages",
        "parameters": [
          {
            "name": "projectid",
            "in": "path",
            "description": "ID of project",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "pageroundid",
            "in": "query",
            "description": "Page round IDs to return, if not set all page rounds are returned. To request multiple page rounds, append with [] and pass one per desired page round (e.g. pageroundid[]=OCR&pageroundid[]=P3).",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Page details",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/project_page_detail"
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimitExceeded"
          },
          "default": {
            "$ref": "#/components/responses/UnexpectedError"
          }
        }
      }
    },
    "/projects/{projectid}/pages/{pagename}/pagerounds/{pageroundid}": {
      "get": {
        "tags": [
          "project"
        ],
        "description": "Gets a project page text in a given pageround",
        "parameters": [
          {
            "name": "projectid",
            "in": "path",
            "description": "ID of project",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "pagename",
            "in": "path",
            "description": "Name of page",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "pageroundid",
            "in": "path",
            "description": "Page round ID",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Project page information",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/project_page"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimitExceeded"
          },
          "default": {
            "$ref": "#/components/responses/UnexpectedError"
          }
        }
      }
    },
    "/projects/{projectid}/transitions": {
      "get": {
        "tags": [
          "project"
        ],
        "description": "Gets a list of a project's transitions",
        "parameters": [
          {
            "name": "projectid",
            "in": "path",
            "description": "ID of project",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "List of a project's transitions, ordered by ascending time",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/project_transition"
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimitExceeded"
          },
          "default": {
            "$ref": "#/components/responses/UnexpectedError"
          }
        }
      }
    },
    "/queues": {
      "get": {
        "tags": [
          "queues"
        ],
        "description": "Gets the release queues for a round (or all rounds)",
        "parameters": [
          {
            "name": "roundid",
            "in": "query",
            "description": "Round ID for queues (all rounds if not provided)",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "field",
            "description": "Queue field to return, if not set all fields are returned. <br><br> To request multiple fields, append with [] and pass one per desired field (e.g. field[]=projectid&field[]=author).",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "show",
            "description": "Which queues to show. <dl> <dt>all</dt> <dd>all queues</dd> <dt>enabled</dt> <dd>queues that are enabled</dd> <dt>populated</dt> <dd>queues that are enabled and have projects to release</dd> </dl>",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "all",
                "enabled",
                "populated"
              ]
            }
          },
          {
            "name": "name",
            "description": "Release queue name substring to match. If not set, all queues are returned. <br><br> To request multiple possible queue names (results ORed together), append with [] and pass one per desired name (e.g. name[]=Klingon&name[]=Shakespeare).",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "group",
            "description": "Release queue group name substring to match. If not set all groups are returned (as well as all matching queues in those groups). <br><br> To match multiple possible group names (results ORed together), append with [] and pass one per desired name (e.g. group[]=PM&group[]=Math).",
            "in": "query",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Requested release queue list",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/release_queue_detail"
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimitExceeded"
          },
          "default": {
            "$ref": "#/components/responses/UnexpectedError"
          }
        }
      }
    },
    "/queues/{queueid}/stats": {
      "get": {
        "tags": [
          "queues"
        ],
        "description": "Get release queue stats",
        "parameters": [
          {
            "name": "queueid",
            "in": "path",
            "description": "Queue ID",
            "required": true,
            "schema": {
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Release queue stats",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "type": "object",
                    "properties": {
                      "days_ago": {
                        "type": "integer"
                      },
                      "projects_released": {
                        "type": "integer"
                      },
                      "pages_released": {
                        "type": "integer"
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimitExceeded"
          },
          "default": {
            "$ref": "#/components/responses/UnexpectedError"
          }
        }
      }
    },
    "/queues/{queueid}/projects": {
      "get": {
        "tags": [
          "queues"
        ],
        "description": "Get projects in release queue",
        "parameters": [
          {
            "name": "queueid",
            "in": "path",
            "description": "Queue ID",
            "required": true,
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "unheld_only",
            "in": "query",
            "schema": {
              "type": "boolean"
            }
          },
          {
            "name": "field",
            "description": "Project field to return, if not set all fields are returned. <br><br> To request multiple fields, append with [] and pass one per desired field (e.g. field[]=title&field[]=author).",
            "in": "query",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Release queue projects",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "type": "object",
                    "properties": {
                      "projectid": {
                        "type": "string"
                      },
                      "title": {
                        "type": "string"
                      },
                      "author": {
                        "type": "string"
                      },
                      "project_manager": {
                        "type": "string"
                      },
                      "languages": {
                        "type": "array",
                        "items": {
                          "type": "string"
                        },
                        "minItems": 1,
                        "maxItems": 2
                      },
                      "genre": {
                        "type": "string"
                      },
                      "difficulty": {
                        "type": "string"
                      },
                      "last_state_change_time": {
                        "type": "string",
                        "format": "dateTime"
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimitExceeded"
          },
          "default": {
            "$ref": "#/components/responses/UnexpectedError"
          }
        }
      }
    },
    "/queues/{queueid}": {
      "get": {
        "tags": [
          "queues"
        ],
        "description": "Get release queue information",
        "parameters": [
          {
            "name": "queueid",
            "in": "path",
            "description": "Queue ID",
            "required": true,
            "schema": {
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Release queue information",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "$ref": "#/components/schemas/release_queue_detail"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimitExceeded"
          },
          "default": {
            "$ref": "#/components/responses/UnexpectedError"
          }
        }
      }
    },
    "/projects/{projectid}/checkout": {
      "put": {
        "tags": [
          "project"
        ],
        "description": "Check out a page for proofreading and return page-level details (current text, image name, etc).",
        "parameters": [
          {
            "$ref": "#/components/parameters/projectid"
          },
          {
            "$ref": "#/components/parameters/state_query"
          }
        ],
        "responses": {
          "200": {
            "description": "page data",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/proof_page"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/InvalidValue"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimitExceeded"
          },
          "default": {
            "$ref": "#/components/responses/UnexpectedError"
          }
        }
      }
    },
    "/projects/{projectid}/validatetext": {
      "put": {
        "tags": [
          "project"
        ],
        "description": "Checks the given text for invalid characters and returns any found with their names",
        "parameters": [
          {
            "$ref": "#/components/parameters/projectid"
          }
        ],
        "requestBody": {
          "$ref": "#/components/requestBodies/page_text"
        },
        "responses": {
          "200": {
            "description": "invalid characters",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "invalid_chars": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "additionalProperties": {
                          "type": "string"
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/InvalidValue"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimitExceeded"
          },
          "default": {
            "$ref": "#/components/responses/UnexpectedError"
          }
        }
      }
    },
    "/projects/{projectid}/wordcheck": {
      "put": {
        "tags": [
          "project"
        ],
        "description": "Checks the given text for bad words, returns an array of bad words with their type and an array of messages",
        "parameters": [
          {
            "$ref": "#/components/parameters/projectid"
          }
        ],
        "requestBody": {
          "description": "text, accepted words and languages",
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "text": {
                    "type": "string"
                  },
                  "accepted_words": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    }
                  },
                  "languages": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "wordcheck data",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "bad_words": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "additionalProperties": {
                          "type": "integer",
                          "description": "Keys are bad words, values are levels"
                        }
                      }
                    },
                    "messages": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/InvalidValue"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimitExceeded"
          },
          "default": {
            "$ref": "#/components/responses/UnexpectedError"
          }
        }
      }
    },
    "/projects/{projectid}/pickersets": {
      "get": {
        "tags": [
          "project"
        ],
        "description": "Gets pickersets for the project including utf8 character names",
        "parameters": [
          {
            "$ref": "#/components/parameters/projectid"
          }
        ],
        "responses": {
          "200": {
            "description": "picker data",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "type": "object",
                    "properties": {
                      "name": {
                        "type": "string",
                        "example": "basic-latin"
                      },
                      "subsets": {
                        "type": "array",
                        "items": {
                          "type": "object",
                          "properties": {
                            "name": {
                              "type": "string"
                            },
                            "title": {
                              "type": "string"
                            },
                            "rows": {
                              "type": "array",
                              "items": {
                                "type": "array",
                                "items": {
                                  "type": "string"
                                }
                              }
                            }
                          },
                          "example": {
                            "name": "ˆ",
                            "title": "Letters with acute, grave, and circumflex",
                            "rows": [
                              [
                                [
                                  "Á",
                                  "LATIN CAPITAL LETTER A WITH ACUTE"
                                ],
                                [
                                  "É",
                                  "LATIN CAPITAL LETTER E WITH ACUTE"
                                ]
                              ],
                              [
                                [
                                  "á",
                                  "LATIN SMALL LETTER A WITH ACUTE"
                                ],
                                [
                                  "é",
                                  "LATIN SMALL LETTER E WITH ACUTE"
                                ]
                              ]
                            ]
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/InvalidValue"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimitExceeded"
          },
          "default": {
            "$ref": "#/components/responses/UnexpectedError"
          }
        }
      }
    },
    "/projects/{projectid}/pages/{pagename}": {
      "put": {
        "tags": [
          "project"
        ],
        "description": "Various operations on the page as determined by the 'pageaction' parameter",
        "parameters": [
          {
            "$ref": "#/components/parameters/projectid"
          },
          {
            "$ref": "#/components/parameters/state_query"
          },
          {
            "$ref": "#/components/parameters/pagename"
          },
          {
            "$ref": "#/components/parameters/pagestate_query"
          },
          {
            "name": "pageaction",
            "in": "query",
            "description": "Action to perform on the page. <br><br> resume - The page state can be 'out', 'temp' or 'saved'. If the state is 'saved' it is changed to 'temp'. Returns page-level details (current text, image name, etc). Response:- proof_page object. <br><br> checkin - Checks the page for invalid characters and if valid, saves it as done. Response:- checkin_response object. <br><br> save - Checks the page for invalid characters and if valid, saves it as in progress. Response:- page_text_state object. <br><br> revert - Checks the page for invalid characters and if valid, saves it as in progress. Response:- page_text_state object. <br><br> abandon - Returns the page to the round, response:- none.",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "$ref": "#/components/requestBodies/page_text"
        },
        "responses": {
          "200": {
            "description": "Page data",
            "content": {
              "application/json": {
                "schema": {
                  "oneOf": [
                    {
                      "$ref": "#/components/schemas/checkin_response"
                    },
                    {
                      "$ref": "#/components/schemas/proof_page"
                    },
                    {
                      "$ref": "#/components/schemas/page_text_state"
                    }
                  ]
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/InvalidValue"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimitExceeded"
          },
          "default": {
            "$ref": "#/components/responses/UnexpectedError"
          }
        }
      },
      "get": {
        "tags": [
          "project"
        ],
        "description": "Get page text and state",
        "parameters": [
          {
            "$ref": "#/components/parameters/projectid"
          },
          {
            "$ref": "#/components/parameters/pagename"
          }
        ],
        "responses": {
          "200": {
            "description": "Page data",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/page_text_state"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/InvalidValue"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimitExceeded"
          },
          "default": {
            "$ref": "#/components/responses/UnexpectedError"
          }
        }
      }
    },
    "/projects/{projectid}/pages/{pagename}/wordcheck": {
      "put": {
        "tags": [
          "project"
        ],
        "description": "Report wordcheck reults",
        "parameters": [
          {
            "$ref": "#/components/parameters/projectid"
          },
          {
            "$ref": "#/components/parameters/pagename"
          }
        ],
        "requestBody": {
          "description": "accepted words if any",
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "accepted_words": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK"
          },
          "400": {
            "$ref": "#/components/responses/InvalidValue"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimitExceeded"
          },
          "default": {
            "$ref": "#/components/responses/UnexpectedError"
          }
        }
      }
    },
    "/projects/{projectid}/pages/{pagename}/reportbad": {
      "put": {
        "tags": [
          "project"
        ],
        "description": "Mark a page as bad",
        "parameters": [
          {
            "$ref": "#/components/parameters/projectid"
          },
          {
            "$ref": "#/components/parameters/pagename"
          }
        ],
        "requestBody": {
          "description": "reason for badness",
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "reason": {
                    "type": "string",
                    "enum": [
                      "missing_image",
                      "missing_text",
                      "image_text_mismatch",
                      "corrupted_image",
                      "other"
                    ]
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK"
          },
          "400": {
            "$ref": "#/components/responses/InvalidValue"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimitExceeded"
          },
          "default": {
            "$ref": "#/components/responses/UnexpectedError"
          }
        }
      }
    },
    "/stats/site": {
      "get": {
        "tags": [
          "stats"
        ],
        "description": "Get site statistics",
        "responses": {
          "200": {
            "description": "Site statistics",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/site_stats"
                }
              }
            }
          }
        }
      }
    },
    "/stats/site/projects/stages": {
      "get": {
        "tags": [
          "stats"
        ],
        "description": "Gets site statistics for the number of projects in all stages",
        "responses": {
          "200": {
            "description": "Requested project statistics",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": {
                    "$ref": "#/components/schemas/project_stats"
                  }
                }
              }
            }
          }
        }
      }
    },
    "/stats/site/projects/states": {
      "get": {
        "tags": [
          "stats"
        ],
        "description": "Gets site statistics for the number of projects in all states",
        "responses": {
          "200": {
            "description": "Requested project statistics",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": {
                    "$ref": "#/components/schemas/project_stats"
                  }
                }
              }
            }
          }
        }
      }
    },
    "/stats/site/rounds": {
      "get": {
        "tags": [
          "stats"
        ],
        "description": "Gets the site statistics for all rounds",
        "responses": {
          "200": {
            "description": "Requested round statistics",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": {
                    "$ref": "#/components/schemas/round_stats"
                  }
                }
              }
            }
          }
        }
      }
    },
    "/stats/site/rounds/{roundid}": {
      "get": {
        "tags": [
          "stats"
        ],
        "description": "Gets the site statistics for a round",
        "parameters": [
          {
            "name": "roundid",
            "in": "path",
            "description": "Round ID",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Requested round statistics",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/round_stats"
                }
              }
            }
          }
        }
      }
    },
    "/documents": {
      "get": {
        "tags": [
          "documents"
        ],
        "description": "Gets an array of available documents. If language_code is given, only documents available in that language are returned.",
        "parameters": [
          {
            "name": "language_code",
            "in": "query",
            "description": "Two-letter (ISO 639-1) language code.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Array of document filenames",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "type": "string"
                  }
                }
              }
            }
          }
        }
      }
    },
    "/documents/{document}": {
      "get": {
        "tags": [
          "documents"
        ],
        "description": "Gets a URL for the given document in language_code (if specified and available) or English.",
        "parameters": [
          {
            "name": "document",
            "in": "path",
            "description": "filename of the document",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "language_code",
            "in": "query",
            "description": "Two-letter (ISO 639-1) language code.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "URL for the document",
            "content": {
              "application/json": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      }
    },
    "/dictionaries": {
      "get": {
        "tags": [
          "dictionaries"
        ],
        "description": "Gets an array of languages with dictionaries.",
        "responses": {
          "200": {
            "description": "Array of languages with dictionaries keyed by the language code",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "type": "object"
                  }
                }
              }
            }
          }
        }
      }
    },
    "/storage/{storagekey}": {
      "get": {
        "tags": [
          "storage"
        ],
        "description": "Get JSON blob stored for this storage key",
        "parameters": [
          {
            "name": "storagekey",
            "in": "path",
            "description": "Storage key",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "JSON blob",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          }
        }
      },
      "put": {
        "tags": [
          "storage"
        ],
        "description": "Save JSON blob for this storage key",
        "parameters": [
          {
            "name": "storagekey",
            "in": "path",
            "description": "Storage key",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "JSON blob that was persisted",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          }
        }
      },
      "delete": {
        "tags": [
          "storage"
        ],
        "description": "Delete JSON blob for this storage key",
        "parameters": [
          {
            "name": "storagekey",
            "in": "path",
            "description": "Storage key",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "JSON blob was deleted"
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "ApiKeyAuth": {
        "type": "apiKey",
        "in": "header",
        "name": "X-API-KEY"
      }
    },
    "parameters": {
      "projectid": {
        "name": "projectid",
        "in": "path",
        "description": "ID of project",
        "required": true,
        "schema": {
          "type": "string"
        }
      },
      "state_query": {
        "name": "state",
        "in": "query",
        "description": "Project state",
        "required": true,
        "schema": {
          "type": "string"
        }
      },
      "pagename": {
        "name": "pagename",
        "in": "path",
        "description": "Name of page",
        "required": true,
        "schema": {
          "type": "string"
        }
      },
      "pagestate_query": {
        "name": "pagestate",
        "in": "query",
        "description": "Page state",
        "required": true,
        "schema": {
          "type": "string"
        }
      }
    },
    "requestBodies": {
      "page_text": {
        "description": "Text to save or analyse",
        "content": {
          "application/json": {
            "schema": {
              "type": "object",
              "properties": {
                "text": {
                  "type": "string"
                }
              }
            }
          }
        }
      }
    },
    "schemas": {
      "project": {
        "required": [
          "projectid",
          "title",
          "author",
          "languages",
          "genre",
          "difficulty",
          "project_manager",
          "image_source",
          "character_suites"
        ],
        "type": "object",
        "properties": {
          "projectid": {
            "type": "string",
            "readOnly": true
          },
          "title": {
            "type": "string"
          },
          "author": {
            "type": "string"
          },
          "languages": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "minItems": 1,
            "maxItems": 2
          },
          "genre": {
            "type": "string"
          },
          "difficulty": {
            "type": "string"
          },
          "special_day": {
            "type": "string"
          },
          "project_manager": {
            "type": "string"
          },
          "post_processor": {
            "type": "string",
            "readOnly": true
          },
          "post_process_verifier": {
            "type": "string",
            "readOnly": true
          },
          "image_preparer": {
            "type": "string"
          },
          "text_preparer": {
            "type": "string"
          },
          "image_source": {
            "type": "string"
          },
          "pg_ebook_number": {
            "type": "integer",
            "nullable": true
          },
          "comments": {
            "type": "string"
          },
          "comment_format": {
            "type": "string",
            "enum": [
              "markdown",
              "html"
            ]
          },
          "clearance": {
            "description": "This field will not be included if the requestor is not authorized to see it",
            "type": "string"
          },
          "custom_characters": {
            "type": "string"
          },
          "character_suites": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "minItems": 1
          },
          "state": {
            "type": "string",
            "readOnly": true
          },
          "pages_available": {
            "type": "integer",
            "readOnly": true
          },
          "pages_total": {
            "type": "integer",
            "readOnly": true
          },
          "last_state_change_time": {
            "type": "string",
            "format": "dateTime",
            "readOnly": true
          },
          "last_page_done_time": {
            "type": "string",
            "format": "dateTime",
            "readOnly": true
          },
          "last_edit_time": {
            "type": "string",
            "format": "dateTime",
            "readOnly": true
          },
          "smoothread_deadline": {
            "type": "string",
            "format": "dateTime",
            "readOnly": true
          },
          "forum_url": {
            "type": "string",
            "readOnly": true
          },
          "round_type": {
            "type": "string",
            "readOnly": true
          }
        },
        "description": "A project represents a unique project object in the system. It includes a great deal of information, some fields of which are calculated and not directly modifiable. Not all fields are available to all users. Fields the user does not have access to will not be returned."
      },
      "project_page_index": {
        "required": [
          "image",
          "image_url",
          "image_size"
        ],
        "type": "object",
        "properties": {
          "image": {
            "type": "string"
          },
          "image_url": {
            "type": "string",
            "format": "url"
          },
          "image_size": {
            "type": "integer",
            "description": "Image size in bytes"
          }
        }
      },
      "project_page_detail": {
        "required": [
          "image",
          "image_url",
          "image_size",
          "state"
        ],
        "type": "object",
        "properties": {
          "image": {
            "type": "string"
          },
          "image_url": {
            "type": "string",
            "format": "url"
          },
          "image_size": {
            "type": "integer",
            "description": "Image size in bytes"
          },
          "state": {
            "type": "string"
          },
          "pagerounds": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/project_page_round_detail"
            }
          }
        }
      },
      "project_page_round_detail": {
        "type": "object",
        "required": [
          "page_round",
          "page_size"
        ],
        "properties": {
          "pageround": {
            "type": "string"
          },
          "page_size": {
            "type": "integer",
            "description": "Page size in bytes"
          },
          "is_diff": {
            "type": "boolean",
            "description": "Is there a diff between this and the prior round"
          },
          "user_page_tally": {
            "type": "integer",
            "description": "Number of pages proofer has proofed in this round"
          },
          "wordcheck_ran": {
            "type": "boolean",
            "description": "Was WordCheck run on the page"
          },
          "last_modified": {
            "type": "string",
            "format": "dateTime"
          },
          "username": {
            "description": "This field will not be included if the requestor is not authorized to see it",
            "type": "string"
          }
        }
      },
      "project_artifacts": {
        "type": "array",
        "items": {
          "type": "object",
          "properties": {
            "stage": {
              "type": "string"
            },
            "name": {
              "type": "string"
            },
            "url": {
              "type": "string",
              "format": "url"
            }
          }
        }
      },
      "project_transition": {
        "required": [
          "timestamp",
          "event_type",
          "details"
        ],
        "type": "object",
        "properties": {
          "timestamp": {
            "type": "string",
            "format": "dateTime"
          },
          "event_type": {
            "type": "string",
            "enum": [
              "creation",
              "transition",
              "archive"
            ],
            "description": "<dl> <dt>creation</dt> <dd>Project created</dd> <dt>transition</dt> <dd>Project moves between two stages, eg P3.proj_waiting to P3.proj_avail</dd> <dt>archive</dt> <dd>Project content has been archived and is no longer directly accessible</dd> </dl>"
          },
          "details": {
            "type": "array",
            "items": {
              "type": "string",
              "minItems": 3,
              "maxItems": 3
            }
          }
        }
      },
      "project_page": {
        "required": [
          "pagename"
        ],
        "type": "object",
        "properties": {
          "pagename": {
            "type": "string"
          },
          "image_url": {
            "type": "string"
          },
          "text": {
            "type": "string"
          },
          "state": {
            "type": "string"
          },
          "username": {
            "description": "This field will not be included if the requestor is not authorized to see it",
            "type": "string"
          }
        }
      },
      "release_queue_detail": {
        "properties": {
          "id": {
            "type": "integer"
          },
          "round_id": {
            "type": "string"
          },
          "ordering": {
            "type": "integer"
          },
          "name": {
            "type": "string"
          },
          "enabled": {
            "type": "boolean"
          },
          "populated": {
            "type": "boolean"
          },
          "length": {
            "type": "integer"
          },
          "unheld_length": {
            "type": "integer"
          },
          "comment": {
            "type": "string"
          },
          "project_selector": {
            "type": "string"
          },
          "projects_target": {
            "type": "integer"
          },
          "pages_target": {
            "type": "integer"
          }
        }
      },
      "charsuite": {
        "required": [
          "id"
        ],
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "characters": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "enabled": {
            "type": "boolean"
          }
        }
      },
      "image_source": {
        "required": [
          "id"
        ],
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "name_full": {
            "type": "string"
          },
          "url": {
            "type": "string",
            "format": "url"
          },
          "credit": {
            "type": "string"
          },
          "enabled": {
            "type": "boolean"
          }
        }
      },
      "site_stats": {
        "type": "object",
        "properties": {
          "server_time": {
            "type": "string",
            "format": "dateTime",
            "readOnly": true
          },
          "registered_users": {
            "type": "integer",
            "readOnly": true
          },
          "active_users_1_day": {
            "type": "integer",
            "readOnly": true
          },
          "active_users_7_day": {
            "type": "integer",
            "readOnly": true
          },
          "active_users_30_day": {
            "type": "integer",
            "readOnly": true
          }
        },
        "description": "Statistics for the site"
      },
      "special_day": {
        "type": "object",
        "required": [
          "id"
        ],
        "properties": {
          "id": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "comment": {
            "type": "string"
          },
          "url": {
            "type": "string",
            "format": "url"
          },
          "color": {
            "type": "string"
          },
          "symbol": {
            "type": "string"
          },
          "date_open_month": {
            "type": "integer",
            "description": "Month the special day opens"
          },
          "date_open_day": {
            "type": "integer",
            "description": "Day of the month the special day opens"
          },
          "date_close_month": {
            "type": "integer",
            "description": "Month the special day closes"
          },
          "date_close_day": {
            "type": "integer",
            "description": "Day of the month the special day closes"
          },
          "enabled": {
            "type": "boolean"
          }
        }
      },
      "project_stats": {
        "type": "object",
        "additionalProperties": {
          "type": "integer"
        },
        "description": "Project statistics by state/stage Keys are state/stage ID, values are the number of projects in that state"
      },
      "round_stats": {
        "type": "object",
        "properties": {
          "today_goal": {
            "type": "integer",
            "readOnly": true
          },
          "today_actual": {
            "type": "integer",
            "readOnly": true
          },
          "yesterday_goal": {
            "type": "integer",
            "readOnly": true
          },
          "yesterday_actual": {
            "type": "integer",
            "readOnly": true
          },
          "month_goal": {
            "type": "integer",
            "readOnly": true
          },
          "month_actual": {
            "type": "integer",
            "readOnly": true
          },
          "positive_users": {
            "type": "integer",
            "readOnly": true
          }
        },
        "description": "Statistics for a round"
      },
      "wordlist": {
        "type": "array",
        "items": {
          "type": "string"
        }
      },
      "proof_page": {
        "type": "object",
        "properties": {
          "text": {
            "description": "The page text. If page state is 'out' from OCR or previous round, else from current round",
            "type": "string"
          },
          "pagestate": {
            "description": "The page state, for checking continuity. Either out or temp",
            "type": "string"
          },
          "saved": {
            "description": "True if the page state is 'temp'",
            "type": "boolean"
          },
          "pagename": {
            "description": "The filename of the page with extension",
            "type": "string"
          },
          "image_url": {
            "description": "URL of the image of the page",
            "type": "string"
          },
          "language_direction": {
            "description": "left-to-right or right-to-left",
            "type": "string",
            "enum": [
              "RTL",
              "LTR"
            ]
          },
          "pagenum": {
            "description": "Page \"number\" without extension",
            "type": "string"
          },
          "round_info": {
            "description": "Array of names of proofreaders in earlier rounds",
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        }
      },
      "checkin_response": {
        "type": "object",
        "properties": {
          "message": {
            "description": "message if reached limit, else empty string.",
            "type": "string"
          },
          "status": {
            "description": "1 if limit reached, else 0",
            "type": "integer"
          }
        }
      },
      "page_text_state": {
        "type": "object",
        "properties": {
          "text": {
            "description": "The page text, current or original.",
            "type": "string"
          },
          "pagestate": {
            "description": "The page state, it is now in a 'temp' state since this is returned by save-as-in-progress or save-and-revert-to-original",
            "type": "string"
          },
          "saved": {
            "description": "true if the page has been saved.",
            "type": "boolean"
          }
        }
      },
      "Error": {
        "required": [
          "message",
          "code"
        ],
        "type": "object",
        "properties": {
          "message": {
            "type": "string"
          },
          "code": {
            "type": "integer"
          }
        }
      }
    },
    "responses": {
      "NotFound": {
        "description": "The specified resource was not found",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "Unauthorized": {
        "description": "Unauthorized",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "Forbidden": {
        "description": "Forbidden",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "InvalidValue": {
        "description": "Invalid Value",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "UnexpectedError": {
        "description": "Unexpected Error",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "RateLimitExceeded": {
        "description": "Rate Limit Exceeded",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      }
    }
  },
  "security": [
    {
      "ApiKeyAuth": []
    }
  ]
}